*: move original project to dex
This commit is contained in:
parent
226b88014e
commit
66fe201c24
572 changed files with 121358 additions and 1 deletions
34
.gitignore
vendored
Normal file
34
.gitignore
vendored
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
# Compiled Object files, Static and Dynamic libs (Shared Objects)
|
||||||
|
*.o
|
||||||
|
*.a
|
||||||
|
*.so
|
||||||
|
|
||||||
|
# Folders
|
||||||
|
_obj
|
||||||
|
_test
|
||||||
|
|
||||||
|
# Architecture specific extensions/prefixes
|
||||||
|
*.[568vq]
|
||||||
|
[568vq].out
|
||||||
|
|
||||||
|
*.cgo1.go
|
||||||
|
*.cgo2.c
|
||||||
|
_cgo_defun.c
|
||||||
|
_cgo_gotypes.go
|
||||||
|
_cgo_export.*
|
||||||
|
|
||||||
|
_testmain.go
|
||||||
|
|
||||||
|
*.exe
|
||||||
|
*.test
|
||||||
|
*.prof
|
||||||
|
|
||||||
|
bin/
|
||||||
|
coverage/
|
||||||
|
deploy/
|
||||||
|
Godeps/_workspace/src/github.com/coreos/dex
|
||||||
|
static/fixtures/env.txt
|
||||||
|
static/fixtures/connectors.json
|
||||||
|
static/fixtures/users.json
|
||||||
|
static/fixtures/emailer.json
|
||||||
|
gopath/
|
71
CONTRIBUTING.md
Normal file
71
CONTRIBUTING.md
Normal file
|
@ -0,0 +1,71 @@
|
||||||
|
# How to Contribute
|
||||||
|
|
||||||
|
CoreOS projects are [Apache 2.0 licensed](LICENSE) and accept contributions via
|
||||||
|
GitHub pull requests. This document outlines some of the conventions on
|
||||||
|
development workflow, commit message formatting, contact points and other
|
||||||
|
resources to make it easier to get your contribution accepted.
|
||||||
|
|
||||||
|
# Certificate of Origin
|
||||||
|
|
||||||
|
By contributing to this project you agree to the Developer Certificate of
|
||||||
|
Origin (DCO). This document was created by the Linux Kernel community and is a
|
||||||
|
simple statement that you, as a contributor, have the legal right to make the
|
||||||
|
contribution. See the [DCO](DCO) file for details.
|
||||||
|
|
||||||
|
# Email and Chat
|
||||||
|
|
||||||
|
The project currently uses the general CoreOS email list and IRC channel:
|
||||||
|
- Email: [coreos-dev](https://groups.google.com/forum/#!forum/coreos-dev)
|
||||||
|
- IRC: #[coreos](irc://irc.freenode.org:6667/#coreos) IRC channel on freenode.org
|
||||||
|
|
||||||
|
Please avoid emailing maintainers found in the MAINTAINERS file directly. They
|
||||||
|
are very busy and read the mailing lists.
|
||||||
|
|
||||||
|
## Getting Started
|
||||||
|
|
||||||
|
- Fork the repository on GitHub
|
||||||
|
- Read the [README](README.md) for build and test instructions
|
||||||
|
- Play with the project, submit bugs, submit patches!
|
||||||
|
|
||||||
|
## Contribution Flow
|
||||||
|
|
||||||
|
This is a rough outline of what a contributor's workflow looks like:
|
||||||
|
|
||||||
|
- Create a topic branch from where you want to base your work (usually master).
|
||||||
|
- Make commits of logical units.
|
||||||
|
- Make sure your commit messages are in the proper format (see below).
|
||||||
|
- Push your changes to a topic branch in your fork of the repository.
|
||||||
|
- Make sure the tests pass, and add any new tests as appropriate.
|
||||||
|
- Submit a pull request to the original repository.
|
||||||
|
|
||||||
|
Thanks for your contributions!
|
||||||
|
|
||||||
|
### Format of the Commit Message
|
||||||
|
|
||||||
|
We follow a rough convention for commit messages that is designed to answer two
|
||||||
|
questions: what changed and why. The subject line should feature the what and
|
||||||
|
the body of the commit should describe the why.
|
||||||
|
|
||||||
|
```
|
||||||
|
scripts: add the test-cluster command
|
||||||
|
|
||||||
|
this uses tmux to setup a test cluster that you can easily kill and
|
||||||
|
start for debugging.
|
||||||
|
|
||||||
|
Fixes #38
|
||||||
|
```
|
||||||
|
|
||||||
|
The format can be described more formally as follows:
|
||||||
|
|
||||||
|
```
|
||||||
|
<subsystem>: <what changed>
|
||||||
|
<BLANK LINE>
|
||||||
|
<why this change was made>
|
||||||
|
<BLANK LINE>
|
||||||
|
<footer>
|
||||||
|
```
|
||||||
|
|
||||||
|
The first line is the subject and should be no longer than 70 characters, the
|
||||||
|
second line is always blank, and other lines should be wrapped at 80 characters.
|
||||||
|
This allows the message to be easier to read on GitHub as well as in various
|
||||||
|
git tools.
|
36
DCO
Normal file
36
DCO
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
Developer Certificate of Origin
|
||||||
|
Version 1.1
|
||||||
|
|
||||||
|
Copyright (C) 2004, 2006 The Linux Foundation and its contributors.
|
||||||
|
660 York Street, Suite 102,
|
||||||
|
San Francisco, CA 94110 USA
|
||||||
|
|
||||||
|
Everyone is permitted to copy and distribute verbatim copies of this
|
||||||
|
license document, but changing it is not allowed.
|
||||||
|
|
||||||
|
|
||||||
|
Developer's Certificate of Origin 1.1
|
||||||
|
|
||||||
|
By making a contribution to this project, I certify that:
|
||||||
|
|
||||||
|
(a) The contribution was created in whole or in part by me and I
|
||||||
|
have the right to submit it under the open source license
|
||||||
|
indicated in the file; or
|
||||||
|
|
||||||
|
(b) The contribution is based upon previous work that, to the best
|
||||||
|
of my knowledge, is covered under an appropriate open source
|
||||||
|
license and I have the right under that license to submit that
|
||||||
|
work with modifications, whether created in whole or in part
|
||||||
|
by me, under the same open source license (unless I am
|
||||||
|
permitted to submit under a different license), as indicated
|
||||||
|
in the file; or
|
||||||
|
|
||||||
|
(c) The contribution was provided directly to me by some other
|
||||||
|
person who certified (a), (b) or (c) and I have not modified
|
||||||
|
it.
|
||||||
|
|
||||||
|
(d) I understand and agree that this project and the contribution
|
||||||
|
are public and that a record of the contribution (including all
|
||||||
|
personal information I submit with it, including my sign-off) is
|
||||||
|
maintained indefinitely and may be redistributed consistent with
|
||||||
|
this project or the open source license(s) involved.
|
12
Dockerfile
Normal file
12
Dockerfile
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
FROM quay.io/brianredbeard/corebox
|
||||||
|
|
||||||
|
ADD bin/dex-worker /opt/dex/bin/dex-worker
|
||||||
|
ADD bin/dex-overlord /opt/dex/bin/dex-overlord
|
||||||
|
ADD bin/dexctl /opt/dex/bin/dexctl
|
||||||
|
|
||||||
|
ENV DEX_WORKER_HTML_ASSETS /opt/dex/html/
|
||||||
|
ADD static/html/* $DEX_WORKER_HTML_ASSETS
|
||||||
|
|
||||||
|
ENV DEX_WORKER_EMAIL_ASSETS /opt/dex/email/
|
||||||
|
ADD static/email/* $DEX_WORKER_EMAIL_ASSETS
|
||||||
|
ADD static/fixtures/emailer.json.sample $DEX_WORKER_EMAIL_ASSETS/emailer.json
|
198
Documentation/authorization.md
Normal file
198
Documentation/authorization.md
Normal file
|
@ -0,0 +1,198 @@
|
||||||
|
Authorization (Auth-Z) Proposal
|
||||||
|
===============================
|
||||||
|
|
||||||
|
## Components
|
||||||
|
|
||||||
|
Core-Auth consisists of various components:
|
||||||
|
|
||||||
|
1. A web app for users to authenticate with.
|
||||||
|
2. A web app for users to manage auth-z policies.
|
||||||
|
3. An API to serve auth-z queries.
|
||||||
|
4. A common golang library to: validate auth-n tokens, assert identities from auth-n tokens, and fetch auth-z policies for users.
|
||||||
|
|
||||||
|
## Design Strategy
|
||||||
|
|
||||||
|
- Users authenticate and are provided a JWT
|
||||||
|
- API keys are the same format JWT
|
||||||
|
- Apps use the common library to access core-auth API to fetch auth-z policies etc
|
||||||
|
- Auth-z policy requests supply an etag, policies are cached with a ttl
|
||||||
|
|
||||||
|
## Basic Flow
|
||||||
|
|
||||||
|
1. users log in via OAuth and are redirected to app with token (alternatively entities can use pregenerated api tokens)
|
||||||
|
1. app uses common lib to assert identity from token
|
||||||
|
1. app uses common lib to fetch auth-z policies (if not cached, or ttl expired) from configured auth-z server
|
||||||
|
1. app uses common lib to assert permissions to requested resource(s)
|
||||||
|
input: policies, resource CRN(s)
|
||||||
|
output: yes/no, or filtered list of CRNs
|
||||||
|
1. app responds with: denial, full-results, or filter-results
|
||||||
|
|
||||||
|
|
||||||
|
## Permissions Specification
|
||||||
|
|
||||||
|
### Core Resource Namespaces (CRN)
|
||||||
|
|
||||||
|
Format: `crn:provider:product:instance:resource-type:resource`
|
||||||
|
|
||||||
|
- `provider`: a unique FQDN of the organization that created/maintains the application
|
||||||
|
- `product`: a product id/name unique to the provider
|
||||||
|
- `instance`: an individual deployed instance of the product (FQDN, or UUID?)
|
||||||
|
- `resource-type`: app specific resource type unqiue to the product
|
||||||
|
- `resource`: the uniqe id of the resource in question (can use `/` for nested resources)
|
||||||
|
|
||||||
|
### Resource Namespace Examples
|
||||||
|
|
||||||
|
CoreUpdate Examples:
|
||||||
|
|
||||||
|
```
|
||||||
|
// CoreOS App
|
||||||
|
crn:coreos.com:coreupdate:public.update.core-os.net:app:e96281a6-d1af-4bde-9a0a-97b76e56dc57
|
||||||
|
// CoreOS App's "stable" Group
|
||||||
|
crn:coreos.com:coreupdate:public.update.core-os.net:group:e96281a6-d1af-4bde-9a0a-97b76e56dc57/stable
|
||||||
|
```
|
||||||
|
|
||||||
|
Quay Example:
|
||||||
|
|
||||||
|
```
|
||||||
|
crn:quay.io:enterprise-registry:my-registry.my-company.com:repo:hello-world
|
||||||
|
```
|
||||||
|
|
||||||
|
### Actions
|
||||||
|
|
||||||
|
Similar to CRN but defined and registered by individual apps.
|
||||||
|
Action describes the type of access that should be allowed or denied (for example, read, write, list, delete, startService, and so on)
|
||||||
|
|
||||||
|
```
|
||||||
|
provider:product:name
|
||||||
|
```
|
||||||
|
|
||||||
|
- `provider`: a unique FQDN of the organization that created/maintains the application (same as CRN)
|
||||||
|
- `product`: a product id/name unique to the provider (same as CRN)
|
||||||
|
- `name`: the acutal name of the aciton in the product
|
||||||
|
|
||||||
|
#### Action Examples
|
||||||
|
|
||||||
|
CoreUpdate (general):
|
||||||
|
|
||||||
|
```
|
||||||
|
coreos.com:coreupdate:read
|
||||||
|
coreos.com:coreupdate:write
|
||||||
|
coreos.com:coreupdate:delete
|
||||||
|
```
|
||||||
|
|
||||||
|
CoreUpdate (finer grained control):
|
||||||
|
|
||||||
|
```
|
||||||
|
coreos.com:coreupdate:publish
|
||||||
|
coreos.com:coreupdate:pause
|
||||||
|
coreos.com:coreupdate:modifyBehavior
|
||||||
|
coreos.com:coreupdate:modifyChannel
|
||||||
|
coreos.com:coreupdate:modifyVersion
|
||||||
|
```
|
||||||
|
|
||||||
|
### Policies
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"apiVersion": "v1",
|
||||||
|
"id": "7CFCE45E-610A-407C-84DB-86A24658B217",
|
||||||
|
"label": "my policy",
|
||||||
|
"statements": [
|
||||||
|
{
|
||||||
|
"effect": "allow",
|
||||||
|
"resource": ["crn:..."],
|
||||||
|
"action": ["crn:..."],
|
||||||
|
},
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Policy:
|
||||||
|
|
||||||
|
- `apiVersion`: the policy API version
|
||||||
|
- `id`: unique id of the policy
|
||||||
|
- `label`: human readable label for the policy
|
||||||
|
- `statements`: the main element for a policy. it is a list of multiple statements defining access.
|
||||||
|
|
||||||
|
Statement:
|
||||||
|
|
||||||
|
- `effect`: "allow" or "deny"
|
||||||
|
- `resource`: the CRN of the resource
|
||||||
|
- `action`: described in action section
|
||||||
|
|
||||||
|
#### Policiy Examples
|
||||||
|
|
||||||
|
CoreUpdate Example:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"apiVersion": "v1",
|
||||||
|
"id": "rando-uuid",
|
||||||
|
"label": "admin",
|
||||||
|
"description": "allows full admin access to everything",
|
||||||
|
"statements": [
|
||||||
|
{
|
||||||
|
"effect": "allow",
|
||||||
|
"resource": ["crn:coreos.com:coreupdate:public.update.core-os.net:*:*"],
|
||||||
|
"action": ["coreos.com:coreupdate:*"],
|
||||||
|
},
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
"apiVersion": "v1",
|
||||||
|
"id": "rando-uuid",
|
||||||
|
"label": "full-read-only",
|
||||||
|
"description": "allows read only access to everything",
|
||||||
|
"statements": [
|
||||||
|
{
|
||||||
|
"effect": "allow",
|
||||||
|
"resource": ["crn:coreos.com:coreupdate:public.update.core-os.net:*:*"],
|
||||||
|
"action": ["coreos.com:coreupdate:read"],
|
||||||
|
},
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
"apiVersion": "v1",
|
||||||
|
"id": "rando-uuid",
|
||||||
|
"label": "full-internal-only",
|
||||||
|
"description": "allows read access to everything, denys write access to the main CoreOS app",
|
||||||
|
"statements": [
|
||||||
|
{
|
||||||
|
"effect": "allow",
|
||||||
|
"resource": ["crn:coreos.com:coreupdate:public.update.core-os.net:*:*"],
|
||||||
|
"action": ["coreos.com:coreupdate:read"],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"effect": "deny",
|
||||||
|
"resource": ["crn:coreos.com:coreupdate:public.update.core-os.net:app:e96281a6-d1af-4bde-9a0a-97b76e56dc57"],
|
||||||
|
"action": ["coreos.com:coreupdate:write"],
|
||||||
|
},
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Policy Associations
|
||||||
|
|
||||||
|
Policies can be attached to Organizations, Groups, or Users.
|
||||||
|
|
||||||
|
### Core Auth API
|
||||||
|
|
||||||
|
Should support the following operations:
|
||||||
|
|
||||||
|
- create/delete actions
|
||||||
|
- create/delete resources
|
||||||
|
- get policies for entity
|
||||||
|
- TBD
|
||||||
|
- TBD
|
||||||
|
|
||||||
|
# Open Questions
|
||||||
|
|
||||||
|
- Do we support resource-based permissions?
|
||||||
|
- Do we need to include the org in the CRNs?
|
||||||
|
- Do we version the policies (different than apiVersion) for easy undo/history?
|
||||||
|
- Should we have an `enabled` flag on policies?
|
||||||
|
- How to handle public anonymous access?
|
||||||
|
- Include the AWS equivalent of `NotResource` and `NotAction`?
|
||||||
|
- Do we need to support conditions in policies? Perhaps we don't need these for v1.
|
42
Documentation/oauth2.md
Normal file
42
Documentation/oauth2.md
Normal file
|
@ -0,0 +1,42 @@
|
||||||
|
# dex OAuth 2.0 Implementation
|
||||||
|
|
||||||
|
OAuth 2.0 is defined in [RFC 6749][rfc6749]. The RFC defines the bare minimum necessary to implement OAuth 2.0, while it also describes a set of optional behaviors. This document aims to describe what decisions have been made in dex with respect to those optional behaviors.
|
||||||
|
|
||||||
|
[rfc6749]: https://tools.ietf.org/html/rfc6749
|
||||||
|
|
||||||
|
While the goal of dex is to accurately implement the required aspects of the OAuth 2.0 specification, dex is still under active development and certain disrepancies exist. Any such discrepancies are documented below.
|
||||||
|
|
||||||
|
## TLS
|
||||||
|
|
||||||
|
It is a requirement of OAuth 2.0 (RFC 6749 Section 2.3.1) that any authorization server utilize TLS to protect sensitive information (e.g. client passwords) transmitted between remote parties during the OAuth workflow.
|
||||||
|
From a practical standpoint, TLS can be a tedious requirement for development environments.
|
||||||
|
It also may be desirable to deploy dex behind an SSL-terminating load balancer.
|
||||||
|
dex does not require the use of TLS, but it should be considered necessary when deploying dex on any public networks.
|
||||||
|
|
||||||
|
## Client Authentication
|
||||||
|
|
||||||
|
Unregistered clients are not supported (RFC 6749 Section 2.4).
|
||||||
|
|
||||||
|
## Authorization Endpoint
|
||||||
|
|
||||||
|
User-agent MUST make a valid authorization request to the authorization endpoint (RFC 6749 Section 3.1) using the "authorization code" grant type; no other grant types are supported.
|
||||||
|
Additionally, GET w/ query parameters must be used - POST w/ a form in the request body body is not supported.
|
||||||
|
|
||||||
|
|
||||||
|
The OAuth 2.0 spec leaves the implementation details of the authorization step up to the implementer as long as the request and response formats are respected.
|
||||||
|
dex relies on remote identity providers to fulfill the actual authorization of user-agents.
|
||||||
|
This federated approach typically requires one or more additional HTTP redirects and a manual login step past what is encountered with a typical OAuth 2.0 server.
|
||||||
|
Given this detail, it is necessary that user-agents follow all HTTP redirects during an authorization attempt.
|
||||||
|
Additionally, the HTTP response from the initial authorization request will likely not redirect the user-agent to the redirection endpoint provided in that initial request.
|
||||||
|
User-agent MUST not reject redirections to unrecognized endpoints.
|
||||||
|
|
||||||
|
## Token endpoint
|
||||||
|
|
||||||
|
Clients MUST identify themselves using the Basic HTTP authentication scheme (RFC 6749 Section 2.3.1).
|
||||||
|
Given this requirement, the client_id and client_secret fields of the request are ignored.
|
||||||
|
|
||||||
|
Refresh tokens are never generated and returned.
|
||||||
|
|
||||||
|
Given that the authorization endpoint only supports authorization codes and refresh tokens are never generated, the only supported values of grant_type are "authorization_code" and "client_credentials".
|
||||||
|
|
||||||
|
|
120
Godeps/Godeps.json
generated
Normal file
120
Godeps/Godeps.json
generated
Normal file
|
@ -0,0 +1,120 @@
|
||||||
|
{
|
||||||
|
"ImportPath": "github.com/coreos-inc/auth",
|
||||||
|
"GoVersion": "go1.4.2",
|
||||||
|
"Packages": [
|
||||||
|
"./..."
|
||||||
|
],
|
||||||
|
"Deps": [
|
||||||
|
{
|
||||||
|
"ImportPath": "code.google.com/p/go-uuid/uuid",
|
||||||
|
"Comment": "null-15",
|
||||||
|
"Rev": "35bc42037350f0078e3c974c6ea690f1926603ab"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ImportPath": "github.com/PuerkitoBio/goquery",
|
||||||
|
"Comment": "v0.3.2-79-gb444041",
|
||||||
|
"Rev": "b4440419d81240f8451a505b2f806c853bc2befc"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ImportPath": "github.com/andybalholm/cascadia",
|
||||||
|
"Rev": "6122e68c2642b7b75c538a63b15168c6c80fb757"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ImportPath": "github.com/coopernurse/gorp",
|
||||||
|
"Comment": "v1.7",
|
||||||
|
"Rev": "5d19ebd22fdcf3b9fb1c8cbfcf1d4e78e102f1e0"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ImportPath": "github.com/coreos/go-oidc/http",
|
||||||
|
"Rev": "ee7cb1fb480df22f7d8c4c90199e438e454ca3b6"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ImportPath": "github.com/coreos/go-oidc/jose",
|
||||||
|
"Rev": "ee7cb1fb480df22f7d8c4c90199e438e454ca3b6"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ImportPath": "github.com/coreos/go-oidc/key",
|
||||||
|
"Rev": "ee7cb1fb480df22f7d8c4c90199e438e454ca3b6"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ImportPath": "github.com/coreos/go-oidc/oauth2",
|
||||||
|
"Rev": "ee7cb1fb480df22f7d8c4c90199e438e454ca3b6"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ImportPath": "github.com/coreos/go-oidc/oidc",
|
||||||
|
"Rev": "ee7cb1fb480df22f7d8c4c90199e438e454ca3b6"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ImportPath": "github.com/coreos/pkg/capnslog",
|
||||||
|
"Rev": "fa94270d4bac0d8ae5dc6b71894e251aada93f74"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ImportPath": "github.com/coreos/pkg/flagutil",
|
||||||
|
"Rev": "fa94270d4bac0d8ae5dc6b71894e251aada93f74"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ImportPath": "github.com/coreos/pkg/health",
|
||||||
|
"Rev": "fa94270d4bac0d8ae5dc6b71894e251aada93f74"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ImportPath": "github.com/coreos/pkg/httputil",
|
||||||
|
"Rev": "fa94270d4bac0d8ae5dc6b71894e251aada93f74"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ImportPath": "github.com/coreos/pkg/timeutil",
|
||||||
|
"Rev": "fa94270d4bac0d8ae5dc6b71894e251aada93f74"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ImportPath": "github.com/gorilla/handlers",
|
||||||
|
"Rev": "60c7bfde3e33c201519a200a4507a158cc03a17b"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ImportPath": "github.com/jonboulle/clockwork",
|
||||||
|
"Rev": "3f831b65b61282ba6bece21b91beea2edc4c887a"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ImportPath": "github.com/julienschmidt/httprouter",
|
||||||
|
"Rev": "8c199fb6259ffc1af525cc3ad52ee60ba8359669"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ImportPath": "github.com/kylelemons/godebug/diff",
|
||||||
|
"Rev": "808ac284003ce2b08ef590da08f95379e8a06936"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ImportPath": "github.com/kylelemons/godebug/pretty",
|
||||||
|
"Rev": "808ac284003ce2b08ef590da08f95379e8a06936"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ImportPath": "github.com/lib/pq",
|
||||||
|
"Rev": "7175accbed18058468c07811f76440d6e8d7cf19"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ImportPath": "github.com/mailgun/mailgun-go",
|
||||||
|
"Rev": "9578dc67692294bb7e2a6f4b15dd18c97af19440"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ImportPath": "github.com/mbanzon/simplehttp",
|
||||||
|
"Rev": "04c542e7ac706a25820090f274ea6a4f39a63326"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ImportPath": "golang.org/x/crypto/bcrypt",
|
||||||
|
"Rev": "1fbbd62cfec66bd39d91e97749579579d4d3037e"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ImportPath": "golang.org/x/crypto/blowfish",
|
||||||
|
"Rev": "1fbbd62cfec66bd39d91e97749579579d4d3037e"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ImportPath": "golang.org/x/net/html",
|
||||||
|
"Rev": "dfe268fd2bb5c793f4c083803609fce9806c6f80"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ImportPath": "google.golang.org/api/google-api-go-generator",
|
||||||
|
"Rev": "d3edb0282bde692467788c50070a9211afe75cf3"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ImportPath": "google.golang.org/api/googleapi",
|
||||||
|
"Rev": "d3edb0282bde692467788c50070a9211afe75cf3"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
5
Godeps/Readme
generated
Normal file
5
Godeps/Readme
generated
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
This directory tree is generated automatically by godep.
|
||||||
|
|
||||||
|
Please do not edit.
|
||||||
|
|
||||||
|
See https://github.com/tools/godep for more information.
|
2
Godeps/_workspace/.gitignore
generated
vendored
Normal file
2
Godeps/_workspace/.gitignore
generated
vendored
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
/pkg
|
||||||
|
/bin
|
27
Godeps/_workspace/src/code.google.com/p/go-uuid/uuid/LICENSE
generated
vendored
Normal file
27
Godeps/_workspace/src/code.google.com/p/go-uuid/uuid/LICENSE
generated
vendored
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
Copyright (c) 2009,2014 Google Inc. All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions are
|
||||||
|
met:
|
||||||
|
|
||||||
|
* Redistributions of source code must retain the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer.
|
||||||
|
* Redistributions in binary form must reproduce the above
|
||||||
|
copyright notice, this list of conditions and the following disclaimer
|
||||||
|
in the documentation and/or other materials provided with the
|
||||||
|
distribution.
|
||||||
|
* Neither the name of Google Inc. nor the names of its
|
||||||
|
contributors may be used to endorse or promote products derived from
|
||||||
|
this software without specific prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
84
Godeps/_workspace/src/code.google.com/p/go-uuid/uuid/dce.go
generated
vendored
Normal file
84
Godeps/_workspace/src/code.google.com/p/go-uuid/uuid/dce.go
generated
vendored
Normal file
|
@ -0,0 +1,84 @@
|
||||||
|
// Copyright 2011 Google Inc. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package uuid
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/binary"
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
)
|
||||||
|
|
||||||
|
// A Domain represents a Version 2 domain
|
||||||
|
type Domain byte
|
||||||
|
|
||||||
|
// Domain constants for DCE Security (Version 2) UUIDs.
|
||||||
|
const (
|
||||||
|
Person = Domain(0)
|
||||||
|
Group = Domain(1)
|
||||||
|
Org = Domain(2)
|
||||||
|
)
|
||||||
|
|
||||||
|
// NewDCESecurity returns a DCE Security (Version 2) UUID.
|
||||||
|
//
|
||||||
|
// The domain should be one of Person, Group or Org.
|
||||||
|
// On a POSIX system the id should be the users UID for the Person
|
||||||
|
// domain and the users GID for the Group. The meaning of id for
|
||||||
|
// the domain Org or on non-POSIX systems is site defined.
|
||||||
|
//
|
||||||
|
// For a given domain/id pair the same token may be returned for up to
|
||||||
|
// 7 minutes and 10 seconds.
|
||||||
|
func NewDCESecurity(domain Domain, id uint32) UUID {
|
||||||
|
uuid := NewUUID()
|
||||||
|
if uuid != nil {
|
||||||
|
uuid[6] = (uuid[6] & 0x0f) | 0x20 // Version 2
|
||||||
|
uuid[9] = byte(domain)
|
||||||
|
binary.BigEndian.PutUint32(uuid[0:], id)
|
||||||
|
}
|
||||||
|
return uuid
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewDCEPerson returns a DCE Security (Version 2) UUID in the person
|
||||||
|
// domain with the id returned by os.Getuid.
|
||||||
|
//
|
||||||
|
// NewDCEPerson(Person, uint32(os.Getuid()))
|
||||||
|
func NewDCEPerson() UUID {
|
||||||
|
return NewDCESecurity(Person, uint32(os.Getuid()))
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewDCEGroup returns a DCE Security (Version 2) UUID in the group
|
||||||
|
// domain with the id returned by os.Getgid.
|
||||||
|
//
|
||||||
|
// NewDCEGroup(Group, uint32(os.Getgid()))
|
||||||
|
func NewDCEGroup() UUID {
|
||||||
|
return NewDCESecurity(Group, uint32(os.Getgid()))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Domain returns the domain for a Version 2 UUID or false.
|
||||||
|
func (uuid UUID) Domain() (Domain, bool) {
|
||||||
|
if v, _ := uuid.Version(); v != 2 {
|
||||||
|
return 0, false
|
||||||
|
}
|
||||||
|
return Domain(uuid[9]), true
|
||||||
|
}
|
||||||
|
|
||||||
|
// Id returns the id for a Version 2 UUID or false.
|
||||||
|
func (uuid UUID) Id() (uint32, bool) {
|
||||||
|
if v, _ := uuid.Version(); v != 2 {
|
||||||
|
return 0, false
|
||||||
|
}
|
||||||
|
return binary.BigEndian.Uint32(uuid[0:4]), true
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d Domain) String() string {
|
||||||
|
switch d {
|
||||||
|
case Person:
|
||||||
|
return "Person"
|
||||||
|
case Group:
|
||||||
|
return "Group"
|
||||||
|
case Org:
|
||||||
|
return "Org"
|
||||||
|
}
|
||||||
|
return fmt.Sprintf("Domain%d", int(d))
|
||||||
|
}
|
8
Godeps/_workspace/src/code.google.com/p/go-uuid/uuid/doc.go
generated
vendored
Normal file
8
Godeps/_workspace/src/code.google.com/p/go-uuid/uuid/doc.go
generated
vendored
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
// Copyright 2011 Google Inc. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// The uuid package generates and inspects UUIDs.
|
||||||
|
//
|
||||||
|
// UUIDs are based on RFC 4122 and DCE 1.1: Authentication and Security Services.
|
||||||
|
package uuid
|
53
Godeps/_workspace/src/code.google.com/p/go-uuid/uuid/hash.go
generated
vendored
Normal file
53
Godeps/_workspace/src/code.google.com/p/go-uuid/uuid/hash.go
generated
vendored
Normal file
|
@ -0,0 +1,53 @@
|
||||||
|
// Copyright 2011 Google Inc. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package uuid
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto/md5"
|
||||||
|
"crypto/sha1"
|
||||||
|
"hash"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Well known Name Space IDs and UUIDs
|
||||||
|
var (
|
||||||
|
NameSpace_DNS = Parse("6ba7b810-9dad-11d1-80b4-00c04fd430c8")
|
||||||
|
NameSpace_URL = Parse("6ba7b811-9dad-11d1-80b4-00c04fd430c8")
|
||||||
|
NameSpace_OID = Parse("6ba7b812-9dad-11d1-80b4-00c04fd430c8")
|
||||||
|
NameSpace_X500 = Parse("6ba7b814-9dad-11d1-80b4-00c04fd430c8")
|
||||||
|
NIL = Parse("00000000-0000-0000-0000-000000000000")
|
||||||
|
)
|
||||||
|
|
||||||
|
// NewHash returns a new UUID dervied from the hash of space concatenated with
|
||||||
|
// data generated by h. The hash should be at least 16 byte in length. The
|
||||||
|
// first 16 bytes of the hash are used to form the UUID. The version of the
|
||||||
|
// UUID will be the lower 4 bits of version. NewHash is used to implement
|
||||||
|
// NewMD5 and NewSHA1.
|
||||||
|
func NewHash(h hash.Hash, space UUID, data []byte, version int) UUID {
|
||||||
|
h.Reset()
|
||||||
|
h.Write(space)
|
||||||
|
h.Write([]byte(data))
|
||||||
|
s := h.Sum(nil)
|
||||||
|
uuid := make([]byte, 16)
|
||||||
|
copy(uuid, s)
|
||||||
|
uuid[6] = (uuid[6] & 0x0f) | uint8((version&0xf)<<4)
|
||||||
|
uuid[8] = (uuid[8] & 0x3f) | 0x80 // RFC 4122 variant
|
||||||
|
return uuid
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewMD5 returns a new MD5 (Version 3) UUID based on the
|
||||||
|
// supplied name space and data.
|
||||||
|
//
|
||||||
|
// NewHash(md5.New(), space, data, 3)
|
||||||
|
func NewMD5(space UUID, data []byte) UUID {
|
||||||
|
return NewHash(md5.New(), space, data, 3)
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewSHA1 returns a new SHA1 (Version 5) UUID based on the
|
||||||
|
// supplied name space and data.
|
||||||
|
//
|
||||||
|
// NewHash(sha1.New(), space, data, 5)
|
||||||
|
func NewSHA1(space UUID, data []byte) UUID {
|
||||||
|
return NewHash(sha1.New(), space, data, 5)
|
||||||
|
}
|
30
Godeps/_workspace/src/code.google.com/p/go-uuid/uuid/json.go
generated
vendored
Normal file
30
Godeps/_workspace/src/code.google.com/p/go-uuid/uuid/json.go
generated
vendored
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
// Copyright 2014 Google Inc. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package uuid
|
||||||
|
|
||||||
|
import "errors"
|
||||||
|
|
||||||
|
func (u UUID) MarshalJSON() ([]byte, error) {
|
||||||
|
if len(u) == 0 {
|
||||||
|
return []byte(`""`), nil
|
||||||
|
}
|
||||||
|
return []byte(`"` + u.String() + `"`), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (u *UUID) UnmarshalJSON(data []byte) error {
|
||||||
|
if len(data) == 0 || string(data) == `""` {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
if len(data) < 2 || data[0] != '"' || data[len(data)-1] != '"' {
|
||||||
|
return errors.New("invalid UUID format")
|
||||||
|
}
|
||||||
|
data = data[1 : len(data)-1]
|
||||||
|
uu := Parse(string(data))
|
||||||
|
if uu == nil {
|
||||||
|
return errors.New("invalid UUID format")
|
||||||
|
}
|
||||||
|
*u = uu
|
||||||
|
return nil
|
||||||
|
}
|
32
Godeps/_workspace/src/code.google.com/p/go-uuid/uuid/json_test.go
generated
vendored
Normal file
32
Godeps/_workspace/src/code.google.com/p/go-uuid/uuid/json_test.go
generated
vendored
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
// Copyright 2014 Google Inc. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package uuid
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"reflect"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
var testUUID = Parse("f47ac10b-58cc-0372-8567-0e02b2c3d479")
|
||||||
|
|
||||||
|
func TestJSON(t *testing.T) {
|
||||||
|
type S struct {
|
||||||
|
ID1 UUID
|
||||||
|
ID2 UUID
|
||||||
|
}
|
||||||
|
s1 := S{ID1: testUUID}
|
||||||
|
data, err := json.Marshal(&s1)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
var s2 S
|
||||||
|
if err := json.Unmarshal(data, &s2); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if !reflect.DeepEqual(&s1, &s2) {
|
||||||
|
t.Errorf("got %#v, want %#v", s2, s1)
|
||||||
|
}
|
||||||
|
}
|
101
Godeps/_workspace/src/code.google.com/p/go-uuid/uuid/node.go
generated
vendored
Normal file
101
Godeps/_workspace/src/code.google.com/p/go-uuid/uuid/node.go
generated
vendored
Normal file
|
@ -0,0 +1,101 @@
|
||||||
|
// Copyright 2011 Google Inc. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package uuid
|
||||||
|
|
||||||
|
import "net"
|
||||||
|
|
||||||
|
var (
|
||||||
|
interfaces []net.Interface // cached list of interfaces
|
||||||
|
ifname string // name of interface being used
|
||||||
|
nodeID []byte // hardware for version 1 UUIDs
|
||||||
|
)
|
||||||
|
|
||||||
|
// NodeInterface returns the name of the interface from which the NodeID was
|
||||||
|
// derived. The interface "user" is returned if the NodeID was set by
|
||||||
|
// SetNodeID.
|
||||||
|
func NodeInterface() string {
|
||||||
|
return ifname
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetNodeInterface selects the hardware address to be used for Version 1 UUIDs.
|
||||||
|
// If name is "" then the first usable interface found will be used or a random
|
||||||
|
// Node ID will be generated. If a named interface cannot be found then false
|
||||||
|
// is returned.
|
||||||
|
//
|
||||||
|
// SetNodeInterface never fails when name is "".
|
||||||
|
func SetNodeInterface(name string) bool {
|
||||||
|
if interfaces == nil {
|
||||||
|
var err error
|
||||||
|
interfaces, err = net.Interfaces()
|
||||||
|
if err != nil && name != "" {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, ifs := range interfaces {
|
||||||
|
if len(ifs.HardwareAddr) >= 6 && (name == "" || name == ifs.Name) {
|
||||||
|
if setNodeID(ifs.HardwareAddr) {
|
||||||
|
ifname = ifs.Name
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// We found no interfaces with a valid hardware address. If name
|
||||||
|
// does not specify a specific interface generate a random Node ID
|
||||||
|
// (section 4.1.6)
|
||||||
|
if name == "" {
|
||||||
|
if nodeID == nil {
|
||||||
|
nodeID = make([]byte, 6)
|
||||||
|
}
|
||||||
|
randomBits(nodeID)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// NodeID returns a slice of a copy of the current Node ID, setting the Node ID
|
||||||
|
// if not already set.
|
||||||
|
func NodeID() []byte {
|
||||||
|
if nodeID == nil {
|
||||||
|
SetNodeInterface("")
|
||||||
|
}
|
||||||
|
nid := make([]byte, 6)
|
||||||
|
copy(nid, nodeID)
|
||||||
|
return nid
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetNodeID sets the Node ID to be used for Version 1 UUIDs. The first 6 bytes
|
||||||
|
// of id are used. If id is less than 6 bytes then false is returned and the
|
||||||
|
// Node ID is not set.
|
||||||
|
func SetNodeID(id []byte) bool {
|
||||||
|
if setNodeID(id) {
|
||||||
|
ifname = "user"
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func setNodeID(id []byte) bool {
|
||||||
|
if len(id) < 6 {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if nodeID == nil {
|
||||||
|
nodeID = make([]byte, 6)
|
||||||
|
}
|
||||||
|
copy(nodeID, id)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// NodeID returns the 6 byte node id encoded in uuid. It returns nil if uuid is
|
||||||
|
// not valid. The NodeID is only well defined for version 1 and 2 UUIDs.
|
||||||
|
func (uuid UUID) NodeID() []byte {
|
||||||
|
if len(uuid) != 16 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
node := make([]byte, 6)
|
||||||
|
copy(node, uuid[10:])
|
||||||
|
return node
|
||||||
|
}
|
66
Godeps/_workspace/src/code.google.com/p/go-uuid/uuid/seq_test.go
generated
vendored
Normal file
66
Godeps/_workspace/src/code.google.com/p/go-uuid/uuid/seq_test.go
generated
vendored
Normal file
|
@ -0,0 +1,66 @@
|
||||||
|
// Copyright 2014 Google Inc. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package uuid
|
||||||
|
|
||||||
|
import (
|
||||||
|
"flag"
|
||||||
|
"runtime"
|
||||||
|
"testing"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
// This test is only run when --regressions is passed on the go test line.
|
||||||
|
var regressions = flag.Bool("regressions", false, "run uuid regression tests")
|
||||||
|
|
||||||
|
// TestClockSeqRace tests for a particular race condition of returning two
|
||||||
|
// identical Version1 UUIDs. The duration of 1 minute was chosen as the race
|
||||||
|
// condition, before being fixed, nearly always occured in under 30 seconds.
|
||||||
|
func TestClockSeqRace(t *testing.T) {
|
||||||
|
if !*regressions {
|
||||||
|
t.Skip("skipping regression tests")
|
||||||
|
}
|
||||||
|
duration := time.Minute
|
||||||
|
|
||||||
|
done := make(chan struct{})
|
||||||
|
defer close(done)
|
||||||
|
|
||||||
|
ch := make(chan UUID, 10000)
|
||||||
|
ncpu := runtime.NumCPU()
|
||||||
|
switch ncpu {
|
||||||
|
case 0, 1:
|
||||||
|
// We can't run the test effectively.
|
||||||
|
t.Skip("skipping race test, only one CPU detected")
|
||||||
|
return
|
||||||
|
default:
|
||||||
|
runtime.GOMAXPROCS(ncpu)
|
||||||
|
}
|
||||||
|
for i := 0; i < ncpu; i++ {
|
||||||
|
go func() {
|
||||||
|
for {
|
||||||
|
select {
|
||||||
|
case <-done:
|
||||||
|
return
|
||||||
|
case ch <- NewUUID():
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
|
||||||
|
uuids := make(map[string]bool)
|
||||||
|
cnt := 0
|
||||||
|
start := time.Now()
|
||||||
|
for u := range ch {
|
||||||
|
s := u.String()
|
||||||
|
if uuids[s] {
|
||||||
|
t.Errorf("duplicate uuid after %d in %v: %s", cnt, time.Since(start), s)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
uuids[s] = true
|
||||||
|
if time.Since(start) > duration {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
cnt++
|
||||||
|
}
|
||||||
|
}
|
132
Godeps/_workspace/src/code.google.com/p/go-uuid/uuid/time.go
generated
vendored
Normal file
132
Godeps/_workspace/src/code.google.com/p/go-uuid/uuid/time.go
generated
vendored
Normal file
|
@ -0,0 +1,132 @@
|
||||||
|
// Copyright 2014 Google Inc. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package uuid
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/binary"
|
||||||
|
"sync"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
// A Time represents a time as the number of 100's of nanoseconds since 15 Oct
|
||||||
|
// 1582.
|
||||||
|
type Time int64
|
||||||
|
|
||||||
|
const (
|
||||||
|
lillian = 2299160 // Julian day of 15 Oct 1582
|
||||||
|
unix = 2440587 // Julian day of 1 Jan 1970
|
||||||
|
epoch = unix - lillian // Days between epochs
|
||||||
|
g1582 = epoch * 86400 // seconds between epochs
|
||||||
|
g1582ns100 = g1582 * 10000000 // 100s of a nanoseconds between epochs
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
mu sync.Mutex
|
||||||
|
lasttime uint64 // last time we returned
|
||||||
|
clock_seq uint16 // clock sequence for this run
|
||||||
|
|
||||||
|
timeNow = time.Now // for testing
|
||||||
|
)
|
||||||
|
|
||||||
|
// UnixTime converts t the number of seconds and nanoseconds using the Unix
|
||||||
|
// epoch of 1 Jan 1970.
|
||||||
|
func (t Time) UnixTime() (sec, nsec int64) {
|
||||||
|
sec = int64(t - g1582ns100)
|
||||||
|
nsec = (sec % 10000000) * 100
|
||||||
|
sec /= 10000000
|
||||||
|
return sec, nsec
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetTime returns the current Time (100s of nanoseconds since 15 Oct 1582) and
|
||||||
|
// clock sequence as well as adjusting the clock sequence as needed. An error
|
||||||
|
// is returned if the current time cannot be determined.
|
||||||
|
func GetTime() (Time, uint16, error) {
|
||||||
|
defer mu.Unlock()
|
||||||
|
mu.Lock()
|
||||||
|
return getTime()
|
||||||
|
}
|
||||||
|
|
||||||
|
func getTime() (Time, uint16, error) {
|
||||||
|
t := timeNow()
|
||||||
|
|
||||||
|
// If we don't have a clock sequence already, set one.
|
||||||
|
if clock_seq == 0 {
|
||||||
|
setClockSequence(-1)
|
||||||
|
}
|
||||||
|
now := uint64(t.UnixNano()/100) + g1582ns100
|
||||||
|
|
||||||
|
// If time has gone backwards with this clock sequence then we
|
||||||
|
// increment the clock sequence
|
||||||
|
if now <= lasttime {
|
||||||
|
clock_seq = ((clock_seq + 1) & 0x3fff) | 0x8000
|
||||||
|
}
|
||||||
|
lasttime = now
|
||||||
|
return Time(now), clock_seq, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ClockSequence returns the current clock sequence, generating one if not
|
||||||
|
// already set. The clock sequence is only used for Version 1 UUIDs.
|
||||||
|
//
|
||||||
|
// The uuid package does not use global static storage for the clock sequence or
|
||||||
|
// the last time a UUID was generated. Unless SetClockSequence a new random
|
||||||
|
// clock sequence is generated the first time a clock sequence is requested by
|
||||||
|
// ClockSequence, GetTime, or NewUUID. (section 4.2.1.1) sequence is generated
|
||||||
|
// for
|
||||||
|
func ClockSequence() int {
|
||||||
|
defer mu.Unlock()
|
||||||
|
mu.Lock()
|
||||||
|
return clockSequence()
|
||||||
|
}
|
||||||
|
|
||||||
|
func clockSequence() int {
|
||||||
|
if clock_seq == 0 {
|
||||||
|
setClockSequence(-1)
|
||||||
|
}
|
||||||
|
return int(clock_seq & 0x3fff)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetClockSeq sets the clock sequence to the lower 14 bits of seq. Setting to
|
||||||
|
// -1 causes a new sequence to be generated.
|
||||||
|
func SetClockSequence(seq int) {
|
||||||
|
defer mu.Unlock()
|
||||||
|
mu.Lock()
|
||||||
|
setClockSequence(seq)
|
||||||
|
}
|
||||||
|
|
||||||
|
func setClockSequence(seq int) {
|
||||||
|
if seq == -1 {
|
||||||
|
var b [2]byte
|
||||||
|
randomBits(b[:]) // clock sequence
|
||||||
|
seq = int(b[0])<<8 | int(b[1])
|
||||||
|
}
|
||||||
|
old_seq := clock_seq
|
||||||
|
clock_seq = uint16(seq&0x3fff) | 0x8000 // Set our variant
|
||||||
|
if old_seq != clock_seq {
|
||||||
|
lasttime = 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Time returns the time in 100s of nanoseconds since 15 Oct 1582 encoded in
|
||||||
|
// uuid. It returns false if uuid is not valid. The time is only well defined
|
||||||
|
// for version 1 and 2 UUIDs.
|
||||||
|
func (uuid UUID) Time() (Time, bool) {
|
||||||
|
if len(uuid) != 16 {
|
||||||
|
return 0, false
|
||||||
|
}
|
||||||
|
time := int64(binary.BigEndian.Uint32(uuid[0:4]))
|
||||||
|
time |= int64(binary.BigEndian.Uint16(uuid[4:6])) << 32
|
||||||
|
time |= int64(binary.BigEndian.Uint16(uuid[6:8])&0xfff) << 48
|
||||||
|
return Time(time), true
|
||||||
|
}
|
||||||
|
|
||||||
|
// ClockSequence returns the clock sequence encoded in uuid. It returns false
|
||||||
|
// if uuid is not valid. The clock sequence is only well defined for version 1
|
||||||
|
// and 2 UUIDs.
|
||||||
|
func (uuid UUID) ClockSequence() (int, bool) {
|
||||||
|
if len(uuid) != 16 {
|
||||||
|
return 0, false
|
||||||
|
}
|
||||||
|
return int(binary.BigEndian.Uint16(uuid[8:10])) & 0x3fff, true
|
||||||
|
}
|
43
Godeps/_workspace/src/code.google.com/p/go-uuid/uuid/util.go
generated
vendored
Normal file
43
Godeps/_workspace/src/code.google.com/p/go-uuid/uuid/util.go
generated
vendored
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
// Copyright 2011 Google Inc. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package uuid
|
||||||
|
|
||||||
|
import (
|
||||||
|
"io"
|
||||||
|
)
|
||||||
|
|
||||||
|
// randomBits completely fills slice b with random data.
|
||||||
|
func randomBits(b []byte) {
|
||||||
|
if _, err := io.ReadFull(rander, b); err != nil {
|
||||||
|
panic(err.Error()) // rand should never fail
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// xvalues returns the value of a byte as a hexadecimal digit or 255.
|
||||||
|
var xvalues = []byte{
|
||||||
|
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
|
||||||
|
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
|
||||||
|
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
|
||||||
|
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 255, 255, 255, 255, 255, 255,
|
||||||
|
255, 10, 11, 12, 13, 14, 15, 255, 255, 255, 255, 255, 255, 255, 255, 255,
|
||||||
|
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
|
||||||
|
255, 10, 11, 12, 13, 14, 15, 255, 255, 255, 255, 255, 255, 255, 255, 255,
|
||||||
|
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
|
||||||
|
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
|
||||||
|
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
|
||||||
|
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
|
||||||
|
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
|
||||||
|
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
|
||||||
|
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
|
||||||
|
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
|
||||||
|
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
|
||||||
|
}
|
||||||
|
|
||||||
|
// xtob converts the the first two hex bytes of x into a byte.
|
||||||
|
func xtob(x string) (byte, bool) {
|
||||||
|
b1 := xvalues[x[0]]
|
||||||
|
b2 := xvalues[x[1]]
|
||||||
|
return (b1 << 4) | b2, b1 != 255 && b2 != 255
|
||||||
|
}
|
163
Godeps/_workspace/src/code.google.com/p/go-uuid/uuid/uuid.go
generated
vendored
Normal file
163
Godeps/_workspace/src/code.google.com/p/go-uuid/uuid/uuid.go
generated
vendored
Normal file
|
@ -0,0 +1,163 @@
|
||||||
|
// Copyright 2011 Google Inc. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package uuid
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"crypto/rand"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
// A UUID is a 128 bit (16 byte) Universal Unique IDentifier as defined in RFC
|
||||||
|
// 4122.
|
||||||
|
type UUID []byte
|
||||||
|
|
||||||
|
// A Version represents a UUIDs version.
|
||||||
|
type Version byte
|
||||||
|
|
||||||
|
// A Variant represents a UUIDs variant.
|
||||||
|
type Variant byte
|
||||||
|
|
||||||
|
// Constants returned by Variant.
|
||||||
|
const (
|
||||||
|
Invalid = Variant(iota) // Invalid UUID
|
||||||
|
RFC4122 // The variant specified in RFC4122
|
||||||
|
Reserved // Reserved, NCS backward compatibility.
|
||||||
|
Microsoft // Reserved, Microsoft Corporation backward compatibility.
|
||||||
|
Future // Reserved for future definition.
|
||||||
|
)
|
||||||
|
|
||||||
|
var rander = rand.Reader // random function
|
||||||
|
|
||||||
|
// New returns a new random (version 4) UUID as a string. It is a convenience
|
||||||
|
// function for NewRandom().String().
|
||||||
|
func New() string {
|
||||||
|
return NewRandom().String()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parse decodes s into a UUID or returns nil. Both the UUID form of
|
||||||
|
// xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx and
|
||||||
|
// urn:uuid:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx are decoded.
|
||||||
|
func Parse(s string) UUID {
|
||||||
|
if len(s) == 36+9 {
|
||||||
|
if strings.ToLower(s[:9]) != "urn:uuid:" {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
s = s[9:]
|
||||||
|
} else if len(s) != 36 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
if s[8] != '-' || s[13] != '-' || s[18] != '-' || s[23] != '-' {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
uuid := make([]byte, 16)
|
||||||
|
for i, x := range []int{
|
||||||
|
0, 2, 4, 6,
|
||||||
|
9, 11,
|
||||||
|
14, 16,
|
||||||
|
19, 21,
|
||||||
|
24, 26, 28, 30, 32, 34} {
|
||||||
|
if v, ok := xtob(s[x:]); !ok {
|
||||||
|
return nil
|
||||||
|
} else {
|
||||||
|
uuid[i] = v
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return uuid
|
||||||
|
}
|
||||||
|
|
||||||
|
// Equal returns true if uuid1 and uuid2 are equal.
|
||||||
|
func Equal(uuid1, uuid2 UUID) bool {
|
||||||
|
return bytes.Equal(uuid1, uuid2)
|
||||||
|
}
|
||||||
|
|
||||||
|
// String returns the string form of uuid, xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
|
||||||
|
// , or "" if uuid is invalid.
|
||||||
|
func (uuid UUID) String() string {
|
||||||
|
if uuid == nil || len(uuid) != 16 {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
b := []byte(uuid)
|
||||||
|
return fmt.Sprintf("%08x-%04x-%04x-%04x-%012x",
|
||||||
|
b[:4], b[4:6], b[6:8], b[8:10], b[10:])
|
||||||
|
}
|
||||||
|
|
||||||
|
// URN returns the RFC 2141 URN form of uuid,
|
||||||
|
// urn:uuid:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx, or "" if uuid is invalid.
|
||||||
|
func (uuid UUID) URN() string {
|
||||||
|
if uuid == nil || len(uuid) != 16 {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
b := []byte(uuid)
|
||||||
|
return fmt.Sprintf("urn:uuid:%08x-%04x-%04x-%04x-%012x",
|
||||||
|
b[:4], b[4:6], b[6:8], b[8:10], b[10:])
|
||||||
|
}
|
||||||
|
|
||||||
|
// Variant returns the variant encoded in uuid. It returns Invalid if
|
||||||
|
// uuid is invalid.
|
||||||
|
func (uuid UUID) Variant() Variant {
|
||||||
|
if len(uuid) != 16 {
|
||||||
|
return Invalid
|
||||||
|
}
|
||||||
|
switch {
|
||||||
|
case (uuid[8] & 0xc0) == 0x80:
|
||||||
|
return RFC4122
|
||||||
|
case (uuid[8] & 0xe0) == 0xc0:
|
||||||
|
return Microsoft
|
||||||
|
case (uuid[8] & 0xe0) == 0xe0:
|
||||||
|
return Future
|
||||||
|
default:
|
||||||
|
return Reserved
|
||||||
|
}
|
||||||
|
panic("unreachable")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Version returns the verison of uuid. It returns false if uuid is not
|
||||||
|
// valid.
|
||||||
|
func (uuid UUID) Version() (Version, bool) {
|
||||||
|
if len(uuid) != 16 {
|
||||||
|
return 0, false
|
||||||
|
}
|
||||||
|
return Version(uuid[6] >> 4), true
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v Version) String() string {
|
||||||
|
if v > 15 {
|
||||||
|
return fmt.Sprintf("BAD_VERSION_%d", v)
|
||||||
|
}
|
||||||
|
return fmt.Sprintf("VERSION_%d", v)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v Variant) String() string {
|
||||||
|
switch v {
|
||||||
|
case RFC4122:
|
||||||
|
return "RFC4122"
|
||||||
|
case Reserved:
|
||||||
|
return "Reserved"
|
||||||
|
case Microsoft:
|
||||||
|
return "Microsoft"
|
||||||
|
case Future:
|
||||||
|
return "Future"
|
||||||
|
case Invalid:
|
||||||
|
return "Invalid"
|
||||||
|
}
|
||||||
|
return fmt.Sprintf("BadVariant%d", int(v))
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetRand sets the random number generator to r, which implents io.Reader.
|
||||||
|
// If r.Read returns an error when the package requests random data then
|
||||||
|
// a panic will be issued.
|
||||||
|
//
|
||||||
|
// Calling SetRand with nil sets the random number generator to the default
|
||||||
|
// generator.
|
||||||
|
func SetRand(r io.Reader) {
|
||||||
|
if r == nil {
|
||||||
|
rander = rand.Reader
|
||||||
|
return
|
||||||
|
}
|
||||||
|
rander = r
|
||||||
|
}
|
390
Godeps/_workspace/src/code.google.com/p/go-uuid/uuid/uuid_test.go
generated
vendored
Normal file
390
Godeps/_workspace/src/code.google.com/p/go-uuid/uuid/uuid_test.go
generated
vendored
Normal file
|
@ -0,0 +1,390 @@
|
||||||
|
// Copyright 2011 Google Inc. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package uuid
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"strings"
|
||||||
|
"testing"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
type test struct {
|
||||||
|
in string
|
||||||
|
version Version
|
||||||
|
variant Variant
|
||||||
|
isuuid bool
|
||||||
|
}
|
||||||
|
|
||||||
|
var tests = []test{
|
||||||
|
{"f47ac10b-58cc-0372-8567-0e02b2c3d479", 0, RFC4122, true},
|
||||||
|
{"f47ac10b-58cc-1372-8567-0e02b2c3d479", 1, RFC4122, true},
|
||||||
|
{"f47ac10b-58cc-2372-8567-0e02b2c3d479", 2, RFC4122, true},
|
||||||
|
{"f47ac10b-58cc-3372-8567-0e02b2c3d479", 3, RFC4122, true},
|
||||||
|
{"f47ac10b-58cc-4372-8567-0e02b2c3d479", 4, RFC4122, true},
|
||||||
|
{"f47ac10b-58cc-5372-8567-0e02b2c3d479", 5, RFC4122, true},
|
||||||
|
{"f47ac10b-58cc-6372-8567-0e02b2c3d479", 6, RFC4122, true},
|
||||||
|
{"f47ac10b-58cc-7372-8567-0e02b2c3d479", 7, RFC4122, true},
|
||||||
|
{"f47ac10b-58cc-8372-8567-0e02b2c3d479", 8, RFC4122, true},
|
||||||
|
{"f47ac10b-58cc-9372-8567-0e02b2c3d479", 9, RFC4122, true},
|
||||||
|
{"f47ac10b-58cc-a372-8567-0e02b2c3d479", 10, RFC4122, true},
|
||||||
|
{"f47ac10b-58cc-b372-8567-0e02b2c3d479", 11, RFC4122, true},
|
||||||
|
{"f47ac10b-58cc-c372-8567-0e02b2c3d479", 12, RFC4122, true},
|
||||||
|
{"f47ac10b-58cc-d372-8567-0e02b2c3d479", 13, RFC4122, true},
|
||||||
|
{"f47ac10b-58cc-e372-8567-0e02b2c3d479", 14, RFC4122, true},
|
||||||
|
{"f47ac10b-58cc-f372-8567-0e02b2c3d479", 15, RFC4122, true},
|
||||||
|
|
||||||
|
{"urn:uuid:f47ac10b-58cc-4372-0567-0e02b2c3d479", 4, Reserved, true},
|
||||||
|
{"URN:UUID:f47ac10b-58cc-4372-0567-0e02b2c3d479", 4, Reserved, true},
|
||||||
|
{"f47ac10b-58cc-4372-0567-0e02b2c3d479", 4, Reserved, true},
|
||||||
|
{"f47ac10b-58cc-4372-1567-0e02b2c3d479", 4, Reserved, true},
|
||||||
|
{"f47ac10b-58cc-4372-2567-0e02b2c3d479", 4, Reserved, true},
|
||||||
|
{"f47ac10b-58cc-4372-3567-0e02b2c3d479", 4, Reserved, true},
|
||||||
|
{"f47ac10b-58cc-4372-4567-0e02b2c3d479", 4, Reserved, true},
|
||||||
|
{"f47ac10b-58cc-4372-5567-0e02b2c3d479", 4, Reserved, true},
|
||||||
|
{"f47ac10b-58cc-4372-6567-0e02b2c3d479", 4, Reserved, true},
|
||||||
|
{"f47ac10b-58cc-4372-7567-0e02b2c3d479", 4, Reserved, true},
|
||||||
|
{"f47ac10b-58cc-4372-8567-0e02b2c3d479", 4, RFC4122, true},
|
||||||
|
{"f47ac10b-58cc-4372-9567-0e02b2c3d479", 4, RFC4122, true},
|
||||||
|
{"f47ac10b-58cc-4372-a567-0e02b2c3d479", 4, RFC4122, true},
|
||||||
|
{"f47ac10b-58cc-4372-b567-0e02b2c3d479", 4, RFC4122, true},
|
||||||
|
{"f47ac10b-58cc-4372-c567-0e02b2c3d479", 4, Microsoft, true},
|
||||||
|
{"f47ac10b-58cc-4372-d567-0e02b2c3d479", 4, Microsoft, true},
|
||||||
|
{"f47ac10b-58cc-4372-e567-0e02b2c3d479", 4, Future, true},
|
||||||
|
{"f47ac10b-58cc-4372-f567-0e02b2c3d479", 4, Future, true},
|
||||||
|
|
||||||
|
{"f47ac10b158cc-5372-a567-0e02b2c3d479", 0, Invalid, false},
|
||||||
|
{"f47ac10b-58cc25372-a567-0e02b2c3d479", 0, Invalid, false},
|
||||||
|
{"f47ac10b-58cc-53723a567-0e02b2c3d479", 0, Invalid, false},
|
||||||
|
{"f47ac10b-58cc-5372-a56740e02b2c3d479", 0, Invalid, false},
|
||||||
|
{"f47ac10b-58cc-5372-a567-0e02-2c3d479", 0, Invalid, false},
|
||||||
|
{"g47ac10b-58cc-4372-a567-0e02b2c3d479", 0, Invalid, false},
|
||||||
|
}
|
||||||
|
|
||||||
|
var constants = []struct {
|
||||||
|
c interface{}
|
||||||
|
name string
|
||||||
|
}{
|
||||||
|
{Person, "Person"},
|
||||||
|
{Group, "Group"},
|
||||||
|
{Org, "Org"},
|
||||||
|
{Invalid, "Invalid"},
|
||||||
|
{RFC4122, "RFC4122"},
|
||||||
|
{Reserved, "Reserved"},
|
||||||
|
{Microsoft, "Microsoft"},
|
||||||
|
{Future, "Future"},
|
||||||
|
{Domain(17), "Domain17"},
|
||||||
|
{Variant(42), "BadVariant42"},
|
||||||
|
}
|
||||||
|
|
||||||
|
func testTest(t *testing.T, in string, tt test) {
|
||||||
|
uuid := Parse(in)
|
||||||
|
if ok := (uuid != nil); ok != tt.isuuid {
|
||||||
|
t.Errorf("Parse(%s) got %v expected %v\b", in, ok, tt.isuuid)
|
||||||
|
}
|
||||||
|
if uuid == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if v := uuid.Variant(); v != tt.variant {
|
||||||
|
t.Errorf("Variant(%s) got %d expected %d\b", in, v, tt.variant)
|
||||||
|
}
|
||||||
|
if v, _ := uuid.Version(); v != tt.version {
|
||||||
|
t.Errorf("Version(%s) got %d expected %d\b", in, v, tt.version)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestUUID(t *testing.T) {
|
||||||
|
for _, tt := range tests {
|
||||||
|
testTest(t, tt.in, tt)
|
||||||
|
testTest(t, strings.ToUpper(tt.in), tt)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestConstants(t *testing.T) {
|
||||||
|
for x, tt := range constants {
|
||||||
|
v, ok := tt.c.(fmt.Stringer)
|
||||||
|
if !ok {
|
||||||
|
t.Errorf("%x: %v: not a stringer", x, v)
|
||||||
|
} else if s := v.String(); s != tt.name {
|
||||||
|
v, _ := tt.c.(int)
|
||||||
|
t.Errorf("%x: Constant %T:%d gives %q, expected %q\n", x, tt.c, v, s, tt.name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestRandomUUID(t *testing.T) {
|
||||||
|
m := make(map[string]bool)
|
||||||
|
for x := 1; x < 32; x++ {
|
||||||
|
uuid := NewRandom()
|
||||||
|
s := uuid.String()
|
||||||
|
if m[s] {
|
||||||
|
t.Errorf("NewRandom returned duplicated UUID %s\n", s)
|
||||||
|
}
|
||||||
|
m[s] = true
|
||||||
|
if v, _ := uuid.Version(); v != 4 {
|
||||||
|
t.Errorf("Random UUID of version %s\n", v)
|
||||||
|
}
|
||||||
|
if uuid.Variant() != RFC4122 {
|
||||||
|
t.Errorf("Random UUID is variant %d\n", uuid.Variant())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestNew(t *testing.T) {
|
||||||
|
m := make(map[string]bool)
|
||||||
|
for x := 1; x < 32; x++ {
|
||||||
|
s := New()
|
||||||
|
if m[s] {
|
||||||
|
t.Errorf("New returned duplicated UUID %s\n", s)
|
||||||
|
}
|
||||||
|
m[s] = true
|
||||||
|
uuid := Parse(s)
|
||||||
|
if uuid == nil {
|
||||||
|
t.Errorf("New returned %q which does not decode\n", s)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if v, _ := uuid.Version(); v != 4 {
|
||||||
|
t.Errorf("Random UUID of version %s\n", v)
|
||||||
|
}
|
||||||
|
if uuid.Variant() != RFC4122 {
|
||||||
|
t.Errorf("Random UUID is variant %d\n", uuid.Variant())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func clockSeq(t *testing.T, uuid UUID) int {
|
||||||
|
seq, ok := uuid.ClockSequence()
|
||||||
|
if !ok {
|
||||||
|
t.Fatalf("%s: invalid clock sequence\n", uuid)
|
||||||
|
}
|
||||||
|
return seq
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestClockSeq(t *testing.T) {
|
||||||
|
// Fake time.Now for this test to return a monotonically advancing time; restore it at end.
|
||||||
|
defer func(orig func() time.Time) { timeNow = orig }(timeNow)
|
||||||
|
monTime := time.Now()
|
||||||
|
timeNow = func() time.Time {
|
||||||
|
monTime = monTime.Add(1 * time.Second)
|
||||||
|
return monTime
|
||||||
|
}
|
||||||
|
|
||||||
|
SetClockSequence(-1)
|
||||||
|
uuid1 := NewUUID()
|
||||||
|
uuid2 := NewUUID()
|
||||||
|
|
||||||
|
if clockSeq(t, uuid1) != clockSeq(t, uuid2) {
|
||||||
|
t.Errorf("clock sequence %d != %d\n", clockSeq(t, uuid1), clockSeq(t, uuid2))
|
||||||
|
}
|
||||||
|
|
||||||
|
SetClockSequence(-1)
|
||||||
|
uuid2 = NewUUID()
|
||||||
|
|
||||||
|
// Just on the very off chance we generated the same sequence
|
||||||
|
// two times we try again.
|
||||||
|
if clockSeq(t, uuid1) == clockSeq(t, uuid2) {
|
||||||
|
SetClockSequence(-1)
|
||||||
|
uuid2 = NewUUID()
|
||||||
|
}
|
||||||
|
if clockSeq(t, uuid1) == clockSeq(t, uuid2) {
|
||||||
|
t.Errorf("Duplicate clock sequence %d\n", clockSeq(t, uuid1))
|
||||||
|
}
|
||||||
|
|
||||||
|
SetClockSequence(0x1234)
|
||||||
|
uuid1 = NewUUID()
|
||||||
|
if seq := clockSeq(t, uuid1); seq != 0x1234 {
|
||||||
|
t.Errorf("%s: expected seq 0x1234 got 0x%04x\n", uuid1, seq)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCoding(t *testing.T) {
|
||||||
|
text := "7d444840-9dc0-11d1-b245-5ffdce74fad2"
|
||||||
|
urn := "urn:uuid:7d444840-9dc0-11d1-b245-5ffdce74fad2"
|
||||||
|
data := UUID{
|
||||||
|
0x7d, 0x44, 0x48, 0x40,
|
||||||
|
0x9d, 0xc0,
|
||||||
|
0x11, 0xd1,
|
||||||
|
0xb2, 0x45,
|
||||||
|
0x5f, 0xfd, 0xce, 0x74, 0xfa, 0xd2,
|
||||||
|
}
|
||||||
|
if v := data.String(); v != text {
|
||||||
|
t.Errorf("%x: encoded to %s, expected %s\n", data, v, text)
|
||||||
|
}
|
||||||
|
if v := data.URN(); v != urn {
|
||||||
|
t.Errorf("%x: urn is %s, expected %s\n", data, v, urn)
|
||||||
|
}
|
||||||
|
|
||||||
|
uuid := Parse(text)
|
||||||
|
if !Equal(uuid, data) {
|
||||||
|
t.Errorf("%s: decoded to %s, expected %s\n", text, uuid, data)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestVersion1(t *testing.T) {
|
||||||
|
uuid1 := NewUUID()
|
||||||
|
uuid2 := NewUUID()
|
||||||
|
|
||||||
|
if Equal(uuid1, uuid2) {
|
||||||
|
t.Errorf("%s:duplicate uuid\n", uuid1)
|
||||||
|
}
|
||||||
|
if v, _ := uuid1.Version(); v != 1 {
|
||||||
|
t.Errorf("%s: version %s expected 1\n", uuid1, v)
|
||||||
|
}
|
||||||
|
if v, _ := uuid2.Version(); v != 1 {
|
||||||
|
t.Errorf("%s: version %s expected 1\n", uuid2, v)
|
||||||
|
}
|
||||||
|
n1 := uuid1.NodeID()
|
||||||
|
n2 := uuid2.NodeID()
|
||||||
|
if !bytes.Equal(n1, n2) {
|
||||||
|
t.Errorf("Different nodes %x != %x\n", n1, n2)
|
||||||
|
}
|
||||||
|
t1, ok := uuid1.Time()
|
||||||
|
if !ok {
|
||||||
|
t.Errorf("%s: invalid time\n", uuid1)
|
||||||
|
}
|
||||||
|
t2, ok := uuid2.Time()
|
||||||
|
if !ok {
|
||||||
|
t.Errorf("%s: invalid time\n", uuid2)
|
||||||
|
}
|
||||||
|
q1, ok := uuid1.ClockSequence()
|
||||||
|
if !ok {
|
||||||
|
t.Errorf("%s: invalid clock sequence\n", uuid1)
|
||||||
|
}
|
||||||
|
q2, ok := uuid2.ClockSequence()
|
||||||
|
if !ok {
|
||||||
|
t.Errorf("%s: invalid clock sequence", uuid2)
|
||||||
|
}
|
||||||
|
|
||||||
|
switch {
|
||||||
|
case t1 == t2 && q1 == q2:
|
||||||
|
t.Errorf("time stopped\n")
|
||||||
|
case t1 > t2 && q1 == q2:
|
||||||
|
t.Errorf("time reversed\n")
|
||||||
|
case t1 < t2 && q1 != q2:
|
||||||
|
t.Errorf("clock sequence chaned unexpectedly\n")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestNodeAndTime(t *testing.T) {
|
||||||
|
// Time is February 5, 1998 12:30:23.136364800 AM GMT
|
||||||
|
|
||||||
|
uuid := Parse("7d444840-9dc0-11d1-b245-5ffdce74fad2")
|
||||||
|
node := []byte{0x5f, 0xfd, 0xce, 0x74, 0xfa, 0xd2}
|
||||||
|
|
||||||
|
ts, ok := uuid.Time()
|
||||||
|
if ok {
|
||||||
|
c := time.Unix(ts.UnixTime())
|
||||||
|
want := time.Date(1998, 2, 5, 0, 30, 23, 136364800, time.UTC)
|
||||||
|
if !c.Equal(want) {
|
||||||
|
t.Errorf("Got time %v, want %v", c, want)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
t.Errorf("%s: bad time\n", uuid)
|
||||||
|
}
|
||||||
|
if !bytes.Equal(node, uuid.NodeID()) {
|
||||||
|
t.Errorf("Expected node %v got %v\n", node, uuid.NodeID())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestMD5(t *testing.T) {
|
||||||
|
uuid := NewMD5(NameSpace_DNS, []byte("python.org")).String()
|
||||||
|
want := "6fa459ea-ee8a-3ca4-894e-db77e160355e"
|
||||||
|
if uuid != want {
|
||||||
|
t.Errorf("MD5: got %q expected %q\n", uuid, want)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSHA1(t *testing.T) {
|
||||||
|
uuid := NewSHA1(NameSpace_DNS, []byte("python.org")).String()
|
||||||
|
want := "886313e1-3b8a-5372-9b90-0c9aee199e5d"
|
||||||
|
if uuid != want {
|
||||||
|
t.Errorf("SHA1: got %q expected %q\n", uuid, want)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestNodeID(t *testing.T) {
|
||||||
|
nid := []byte{1, 2, 3, 4, 5, 6}
|
||||||
|
SetNodeInterface("")
|
||||||
|
s := NodeInterface()
|
||||||
|
if s == "" || s == "user" {
|
||||||
|
t.Errorf("NodeInterface %q after SetInteface\n", s)
|
||||||
|
}
|
||||||
|
node1 := NodeID()
|
||||||
|
if node1 == nil {
|
||||||
|
t.Errorf("NodeID nil after SetNodeInterface\n", s)
|
||||||
|
}
|
||||||
|
SetNodeID(nid)
|
||||||
|
s = NodeInterface()
|
||||||
|
if s != "user" {
|
||||||
|
t.Errorf("Expected NodeInterface %q got %q\n", "user", s)
|
||||||
|
}
|
||||||
|
node2 := NodeID()
|
||||||
|
if node2 == nil {
|
||||||
|
t.Errorf("NodeID nil after SetNodeID\n", s)
|
||||||
|
}
|
||||||
|
if bytes.Equal(node1, node2) {
|
||||||
|
t.Errorf("NodeID not changed after SetNodeID\n", s)
|
||||||
|
} else if !bytes.Equal(nid, node2) {
|
||||||
|
t.Errorf("NodeID is %x, expected %x\n", node2, nid)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func testDCE(t *testing.T, name string, uuid UUID, domain Domain, id uint32) {
|
||||||
|
if uuid == nil {
|
||||||
|
t.Errorf("%s failed\n", name)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if v, _ := uuid.Version(); v != 2 {
|
||||||
|
t.Errorf("%s: %s: expected version 2, got %s\n", name, uuid, v)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if v, ok := uuid.Domain(); !ok || v != domain {
|
||||||
|
if !ok {
|
||||||
|
t.Errorf("%s: %d: Domain failed\n", name, uuid)
|
||||||
|
} else {
|
||||||
|
t.Errorf("%s: %s: expected domain %d, got %d\n", name, uuid, domain, v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if v, ok := uuid.Id(); !ok || v != id {
|
||||||
|
if !ok {
|
||||||
|
t.Errorf("%s: %d: Id failed\n", name, uuid)
|
||||||
|
} else {
|
||||||
|
t.Errorf("%s: %s: expected id %d, got %d\n", name, uuid, id, v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestDCE(t *testing.T) {
|
||||||
|
testDCE(t, "NewDCESecurity", NewDCESecurity(42, 12345678), 42, 12345678)
|
||||||
|
testDCE(t, "NewDCEPerson", NewDCEPerson(), Person, uint32(os.Getuid()))
|
||||||
|
testDCE(t, "NewDCEGroup", NewDCEGroup(), Group, uint32(os.Getgid()))
|
||||||
|
}
|
||||||
|
|
||||||
|
type badRand struct{}
|
||||||
|
|
||||||
|
func (r badRand) Read(buf []byte) (int, error) {
|
||||||
|
for i, _ := range buf {
|
||||||
|
buf[i] = byte(i)
|
||||||
|
}
|
||||||
|
return len(buf), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestBadRand(t *testing.T) {
|
||||||
|
SetRand(badRand{})
|
||||||
|
uuid1 := New()
|
||||||
|
uuid2 := New()
|
||||||
|
if uuid1 != uuid2 {
|
||||||
|
t.Errorf("execpted duplicates, got %q and %q\n", uuid1, uuid2)
|
||||||
|
}
|
||||||
|
SetRand(nil)
|
||||||
|
uuid1 = New()
|
||||||
|
uuid2 = New()
|
||||||
|
if uuid1 == uuid2 {
|
||||||
|
t.Errorf("unexecpted duplicates, got %q\n", uuid1)
|
||||||
|
}
|
||||||
|
}
|
41
Godeps/_workspace/src/code.google.com/p/go-uuid/uuid/version1.go
generated
vendored
Normal file
41
Godeps/_workspace/src/code.google.com/p/go-uuid/uuid/version1.go
generated
vendored
Normal file
|
@ -0,0 +1,41 @@
|
||||||
|
// Copyright 2011 Google Inc. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package uuid
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/binary"
|
||||||
|
)
|
||||||
|
|
||||||
|
// NewUUID returns a Version 1 UUID based on the current NodeID and clock
|
||||||
|
// sequence, and the current time. If the NodeID has not been set by SetNodeID
|
||||||
|
// or SetNodeInterface then it will be set automatically. If the NodeID cannot
|
||||||
|
// be set NewUUID returns nil. If clock sequence has not been set by
|
||||||
|
// SetClockSequence then it will be set automatically. If GetTime fails to
|
||||||
|
// return the current NewUUID returns nil.
|
||||||
|
func NewUUID() UUID {
|
||||||
|
if nodeID == nil {
|
||||||
|
SetNodeInterface("")
|
||||||
|
}
|
||||||
|
|
||||||
|
now, seq, err := GetTime()
|
||||||
|
if err != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
uuid := make([]byte, 16)
|
||||||
|
|
||||||
|
time_low := uint32(now & 0xffffffff)
|
||||||
|
time_mid := uint16((now >> 32) & 0xffff)
|
||||||
|
time_hi := uint16((now >> 48) & 0x0fff)
|
||||||
|
time_hi |= 0x1000 // Version 1
|
||||||
|
|
||||||
|
binary.BigEndian.PutUint32(uuid[0:], time_low)
|
||||||
|
binary.BigEndian.PutUint16(uuid[4:], time_mid)
|
||||||
|
binary.BigEndian.PutUint16(uuid[6:], time_hi)
|
||||||
|
binary.BigEndian.PutUint16(uuid[8:], seq)
|
||||||
|
copy(uuid[10:], nodeID)
|
||||||
|
|
||||||
|
return uuid
|
||||||
|
}
|
25
Godeps/_workspace/src/code.google.com/p/go-uuid/uuid/version4.go
generated
vendored
Normal file
25
Godeps/_workspace/src/code.google.com/p/go-uuid/uuid/version4.go
generated
vendored
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
// Copyright 2011 Google Inc. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package uuid
|
||||||
|
|
||||||
|
// Random returns a Random (Version 4) UUID or panics.
|
||||||
|
//
|
||||||
|
// The strength of the UUIDs is based on the strength of the crypto/rand
|
||||||
|
// package.
|
||||||
|
//
|
||||||
|
// A note about uniqueness derived from from the UUID Wikipedia entry:
|
||||||
|
//
|
||||||
|
// Randomly generated UUIDs have 122 random bits. One's annual risk of being
|
||||||
|
// hit by a meteorite is estimated to be one chance in 17 billion, that
|
||||||
|
// means the probability is about 0.00000000006 (6 × 10−11),
|
||||||
|
// equivalent to the odds of creating a few tens of trillions of UUIDs in a
|
||||||
|
// year and having one duplicate.
|
||||||
|
func NewRandom() UUID {
|
||||||
|
uuid := make([]byte, 16)
|
||||||
|
randomBits([]byte(uuid))
|
||||||
|
uuid[6] = (uuid[6] & 0x0f) | 0x40 // Version 4
|
||||||
|
uuid[8] = (uuid[8] & 0x3f) | 0x80 // Variant is 10
|
||||||
|
return uuid
|
||||||
|
}
|
7
Godeps/_workspace/src/github.com/PuerkitoBio/goquery/.gitignore
generated
vendored
Normal file
7
Godeps/_workspace/src/github.com/PuerkitoBio/goquery/.gitignore
generated
vendored
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
*.sublime-*
|
||||||
|
.DS_Store
|
||||||
|
*.swp
|
||||||
|
#*.*#
|
||||||
|
tags
|
||||||
|
goquery.test
|
||||||
|
|
7
Godeps/_workspace/src/github.com/PuerkitoBio/goquery/.travis.yml
generated
vendored
Normal file
7
Godeps/_workspace/src/github.com/PuerkitoBio/goquery/.travis.yml
generated
vendored
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
language: go
|
||||||
|
|
||||||
|
go:
|
||||||
|
- 1.1
|
||||||
|
- 1.2
|
||||||
|
- 1.3
|
||||||
|
- tip
|
12
Godeps/_workspace/src/github.com/PuerkitoBio/goquery/LICENSE
generated
vendored
Normal file
12
Godeps/_workspace/src/github.com/PuerkitoBio/goquery/LICENSE
generated
vendored
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
Copyright (c) 2012-2014, Martin Angers & Contributors
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||||
|
|
||||||
|
* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||||
|
|
||||||
|
* Neither the name of the author nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
113
Godeps/_workspace/src/github.com/PuerkitoBio/goquery/README.md
generated
vendored
Normal file
113
Godeps/_workspace/src/github.com/PuerkitoBio/goquery/README.md
generated
vendored
Normal file
|
@ -0,0 +1,113 @@
|
||||||
|
# goquery - a little like that j-thing, only in Go
|
||||||
|
|
||||||
|
[![build status](https://secure.travis-ci.org/PuerkitoBio/goquery.png)](http://travis-ci.org/PuerkitoBio/goquery)
|
||||||
|
|
||||||
|
[![GoDoc](https://godoc.org/github.com/PuerkitoBio/goquery?status.png)](http://godoc.org/github.com/PuerkitoBio/goquery)
|
||||||
|
|
||||||
|
goquery brings a syntax and a set of features similar to [jQuery][] to the [Go language][go]. It is based on Go's [net/html package][html] and the CSS Selector library [cascadia][]. Since the net/html parser returns nodes, and not a full-featured DOM tree, jQuery's stateful manipulation functions (like height(), css(), detach()) have been left off.
|
||||||
|
|
||||||
|
Also, because the net/html parser requires UTF-8 encoding, so does goquery: it is the caller's responsibility to ensure that the source document provides UTF-8 encoded HTML. See the [wiki][] for various options to do this.
|
||||||
|
|
||||||
|
Syntax-wise, it is as close as possible to jQuery, with the same function names when possible, and that warm and fuzzy chainable interface. jQuery being the ultra-popular library that it is, I felt that writing a similar HTML-manipulating library was better to follow its API than to start anew (in the same spirit as Go's `fmt` package), even though some of its methods are less than intuitive (looking at you, [index()][index]...).
|
||||||
|
|
||||||
|
## Installation
|
||||||
|
|
||||||
|
Please note that because of the net/html dependency, goquery requires Go1.1+.
|
||||||
|
|
||||||
|
$ go get github.com/PuerkitoBio/goquery
|
||||||
|
|
||||||
|
(optional) To run unit tests:
|
||||||
|
|
||||||
|
$ cd $GOPATH/src/github.com/PuerkitoBio/goquery
|
||||||
|
$ go test
|
||||||
|
|
||||||
|
(optional) To run benchmarks (warning: it runs for a few minutes):
|
||||||
|
|
||||||
|
$ cd $GOPATH/src/github.com/PuerkitoBio/goquery
|
||||||
|
$ go test -bench=".*"
|
||||||
|
|
||||||
|
## Changelog
|
||||||
|
|
||||||
|
**Note that goquery's API is now stable, and will not break.**
|
||||||
|
|
||||||
|
* **2015-04-20** : Add `AttrOr` helper method to return the attribute's value or a default value if absent. Thanks to [piotrkowalczuk][piotr].
|
||||||
|
* **2015-02-04** : Add more manipulation functions - Prepend* - thanks again to [Andrew Stone][thatguystone].
|
||||||
|
* **2014-11-28** : Add more manipulation functions - ReplaceWith*, Wrap* and Unwrap - thanks again to [Andrew Stone][thatguystone].
|
||||||
|
* **2014-11-07** : Add manipulation functions (thanks to [Andrew Stone][thatguystone]) and `*Matcher` functions, that receive compiled cascadia selectors instead of selector strings, thus avoiding potential panics thrown by goquery via `cascadia.MustCompile` calls. This results in better performance (selectors can be compiled once and reused) and more idiomatic error handling (you can handle cascadia's compilation errors, instead of recovering from panics, which had been bugging me for a long time). Note that the actual type expected is a `Matcher` interface, that `cascadia.Selector` implements. Other matcher implementations could be used.
|
||||||
|
* **2014-11-06** : Change import paths of net/html to golang.org/x/net/html (see https://groups.google.com/forum/#!topic/golang-nuts/eD8dh3T9yyA). Make sure to update your code to use the new import path too when you call goquery with `html.Node`s.
|
||||||
|
* **v0.3.2** : Add `NewDocumentFromReader()` (thanks jweir) which allows creating a goquery document from an io.Reader.
|
||||||
|
* **v0.3.1** : Add `NewDocumentFromResponse()` (thanks assassingj) which allows creating a goquery document from an http response.
|
||||||
|
* **v0.3.0** : Add `EachWithBreak()` which allows to break out of an `Each()` loop by returning false. This function was added instead of changing the existing `Each()` to avoid breaking compatibility.
|
||||||
|
* **v0.2.1** : Make go-getable, now that [go.net/html is Go1.0-compatible][gonet] (thanks to @matrixik for pointing this out).
|
||||||
|
* **v0.2.0** : Add support for negative indices in Slice(). **BREAKING CHANGE** `Document.Root` is removed, `Document` is now a `Selection` itself (a selection of one, the root element, just like `Document.Root` was before). Add jQuery's Closest() method.
|
||||||
|
* **v0.1.1** : Add benchmarks to use as baseline for refactorings, refactor Next...() and Prev...() methods to use the new html package's linked list features (Next/PrevSibling, FirstChild). Good performance boost (40+% in some cases).
|
||||||
|
* **v0.1.0** : Initial release.
|
||||||
|
|
||||||
|
## API
|
||||||
|
|
||||||
|
goquery exposes two structs, `Document` and `Selection`, and the `Matcher` interface. Unlike jQuery, which is loaded as part of a DOM document, and thus acts on its containing document, goquery doesn't know which HTML document to act upon. So it needs to be told, and that's what the `Document` type is for. It holds the root document node as the initial Selection value to manipulate.
|
||||||
|
|
||||||
|
jQuery often has many variants for the same function (no argument, a selector string argument, a jQuery object argument, a DOM element argument, ...). Instead of exposing the same features in goquery as a single method with variadic empty interface arguments, statically-typed signatures are used following this naming convention:
|
||||||
|
|
||||||
|
* When the jQuery equivalent can be called with no argument, it has the same name as jQuery for the no argument signature (e.g.: `Prev()`), and the version with a selector string argument is called `XxxFiltered()` (e.g.: `PrevFiltered()`)
|
||||||
|
* When the jQuery equivalent **requires** one argument, the same name as jQuery is used for the selector string version (e.g.: `Is()`)
|
||||||
|
* The signatures accepting a jQuery object as argument are defined in goquery as `XxxSelection()` and take a `*Selection` object as argument (e.g.: `FilterSelection()`)
|
||||||
|
* The signatures accepting a DOM element as argument in jQuery are defined in goquery as `XxxNodes()` and take a variadic argument of type `*html.Node` (e.g.: `FilterNodes()`)
|
||||||
|
* The signatures accepting a function as argument in jQuery are defined in goquery as `XxxFunction()` and take a function as argument (e.g.: `FilterFunction()`)
|
||||||
|
* The goquery methods that can be called with a selector string have a corresponding version that take a `Matcher` interface and are defined as `XxxMatcher()` (e.g.: `IsMatcher()`)
|
||||||
|
|
||||||
|
The complete [godoc reference documentation can be found here][doc].
|
||||||
|
|
||||||
|
Please note that Cascadia's selectors do not necessarily match all supported selectors of jQuery (Sizzle). See the [cascadia project][cascadia] for details.
|
||||||
|
|
||||||
|
## Examples
|
||||||
|
|
||||||
|
See some tips and tricks in the [wiki][].
|
||||||
|
|
||||||
|
Taken (and adapted as if executed from outside the goquery package) from example_test.go:
|
||||||
|
|
||||||
|
```Go
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"log"
|
||||||
|
|
||||||
|
"github.com/PuerkitoBio/goquery"
|
||||||
|
)
|
||||||
|
|
||||||
|
func ExampleScrape() {
|
||||||
|
doc, err := goquery.NewDocument("http://metalsucks.net")
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
doc.Find(".reviews-wrap article .review-rhs").Each(func(i int, s *goquery.Selection) {
|
||||||
|
band := s.Find("h3").Text()
|
||||||
|
title := s.Find("i").Text()
|
||||||
|
fmt.Printf("Review %d: %s - %s\n", i, band, title)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
ExampleScrape()
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## License
|
||||||
|
|
||||||
|
The [BSD 3-Clause license][bsd], the same as the [Go language][golic]. Cascadia's license is [here][caslic].
|
||||||
|
|
||||||
|
[jquery]: http://jquery.com/
|
||||||
|
[go]: http://golang.org/
|
||||||
|
[cascadia]: https://github.com/andybalholm/cascadia
|
||||||
|
[bsd]: http://opensource.org/licenses/BSD-3-Clause
|
||||||
|
[golic]: http://golang.org/LICENSE
|
||||||
|
[caslic]: https://github.com/andybalholm/cascadia/blob/master/LICENSE
|
||||||
|
[doc]: http://godoc.org/github.com/PuerkitoBio/goquery
|
||||||
|
[index]: http://api.jquery.com/index/
|
||||||
|
[gonet]: https://github.com/golang/net/
|
||||||
|
[html]: http://godoc.org/golang.org/x/net/html
|
||||||
|
[wiki]: https://github.com/PuerkitoBio/goquery/wiki/Tips-and-tricks
|
||||||
|
[thatguystone]: https://github.com/thatguystone
|
||||||
|
[piotr]: https://github.com/piotrkowalczuk
|
103
Godeps/_workspace/src/github.com/PuerkitoBio/goquery/array.go
generated
vendored
Normal file
103
Godeps/_workspace/src/github.com/PuerkitoBio/goquery/array.go
generated
vendored
Normal file
|
@ -0,0 +1,103 @@
|
||||||
|
package goquery
|
||||||
|
|
||||||
|
import (
|
||||||
|
"golang.org/x/net/html"
|
||||||
|
)
|
||||||
|
|
||||||
|
// First reduces the set of matched elements to the first in the set.
|
||||||
|
// It returns a new Selection object, and an empty Selection object if the
|
||||||
|
// the selection is empty.
|
||||||
|
func (s *Selection) First() *Selection {
|
||||||
|
return s.Eq(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Last reduces the set of matched elements to the last in the set.
|
||||||
|
// It returns a new Selection object, and an empty Selection object if
|
||||||
|
// the selection is empty.
|
||||||
|
func (s *Selection) Last() *Selection {
|
||||||
|
return s.Eq(-1)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Eq reduces the set of matched elements to the one at the specified index.
|
||||||
|
// If a negative index is given, it counts backwards starting at the end of the
|
||||||
|
// set. It returns a new Selection object, and an empty Selection object if the
|
||||||
|
// index is invalid.
|
||||||
|
func (s *Selection) Eq(index int) *Selection {
|
||||||
|
if index < 0 {
|
||||||
|
index += len(s.Nodes)
|
||||||
|
}
|
||||||
|
|
||||||
|
if index >= len(s.Nodes) || index < 0 {
|
||||||
|
return newEmptySelection(s.document)
|
||||||
|
}
|
||||||
|
|
||||||
|
return s.Slice(index, index+1)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Slice reduces the set of matched elements to a subset specified by a range
|
||||||
|
// of indices.
|
||||||
|
func (s *Selection) Slice(start, end int) *Selection {
|
||||||
|
if start < 0 {
|
||||||
|
start += len(s.Nodes)
|
||||||
|
}
|
||||||
|
if end < 0 {
|
||||||
|
end += len(s.Nodes)
|
||||||
|
}
|
||||||
|
return pushStack(s, s.Nodes[start:end])
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get retrieves the underlying node at the specified index.
|
||||||
|
// Get without parameter is not implemented, since the node array is available
|
||||||
|
// on the Selection object.
|
||||||
|
func (s *Selection) Get(index int) *html.Node {
|
||||||
|
if index < 0 {
|
||||||
|
index += len(s.Nodes) // Negative index gets from the end
|
||||||
|
}
|
||||||
|
return s.Nodes[index]
|
||||||
|
}
|
||||||
|
|
||||||
|
// Index returns the position of the first element within the Selection object
|
||||||
|
// relative to its sibling elements.
|
||||||
|
func (s *Selection) Index() int {
|
||||||
|
if len(s.Nodes) > 0 {
|
||||||
|
return newSingleSelection(s.Nodes[0], s.document).PrevAll().Length()
|
||||||
|
}
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
|
||||||
|
// IndexSelector returns the position of the first element within the
|
||||||
|
// Selection object relative to the elements matched by the selector, or -1 if
|
||||||
|
// not found.
|
||||||
|
func (s *Selection) IndexSelector(selector string) int {
|
||||||
|
if len(s.Nodes) > 0 {
|
||||||
|
sel := s.document.Find(selector)
|
||||||
|
return indexInSlice(sel.Nodes, s.Nodes[0])
|
||||||
|
}
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
|
||||||
|
// IndexMatcher returns the position of the first element within the
|
||||||
|
// Selection object relative to the elements matched by the matcher, or -1 if
|
||||||
|
// not found.
|
||||||
|
func (s *Selection) IndexMatcher(m Matcher) int {
|
||||||
|
if len(s.Nodes) > 0 {
|
||||||
|
sel := s.document.FindMatcher(m)
|
||||||
|
return indexInSlice(sel.Nodes, s.Nodes[0])
|
||||||
|
}
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
|
||||||
|
// IndexOfNode returns the position of the specified node within the Selection
|
||||||
|
// object, or -1 if not found.
|
||||||
|
func (s *Selection) IndexOfNode(node *html.Node) int {
|
||||||
|
return indexInSlice(s.Nodes, node)
|
||||||
|
}
|
||||||
|
|
||||||
|
// IndexOfSelection returns the position of the first node in the specified
|
||||||
|
// Selection object within this Selection object, or -1 if not found.
|
||||||
|
func (s *Selection) IndexOfSelection(sel *Selection) int {
|
||||||
|
if sel != nil && len(sel.Nodes) > 0 {
|
||||||
|
return indexInSlice(s.Nodes, sel.Nodes[0])
|
||||||
|
}
|
||||||
|
return -1
|
||||||
|
}
|
180
Godeps/_workspace/src/github.com/PuerkitoBio/goquery/array_test.go
generated
vendored
Normal file
180
Godeps/_workspace/src/github.com/PuerkitoBio/goquery/array_test.go
generated
vendored
Normal file
|
@ -0,0 +1,180 @@
|
||||||
|
package goquery
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestFirst(t *testing.T) {
|
||||||
|
sel := Doc().Find(".pvk-content").First()
|
||||||
|
assertLength(t, sel.Nodes, 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestFirstEmpty(t *testing.T) {
|
||||||
|
sel := Doc().Find(".pvk-zzcontentzz").First()
|
||||||
|
assertLength(t, sel.Nodes, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestFirstRollback(t *testing.T) {
|
||||||
|
sel := Doc().Find(".pvk-content")
|
||||||
|
sel2 := sel.First().End()
|
||||||
|
assertEqual(t, sel, sel2)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestLast(t *testing.T) {
|
||||||
|
sel := Doc().Find(".pvk-content").Last()
|
||||||
|
assertLength(t, sel.Nodes, 1)
|
||||||
|
|
||||||
|
// Should contain Footer
|
||||||
|
foot := Doc().Find(".footer")
|
||||||
|
if !sel.Contains(foot.Nodes[0]) {
|
||||||
|
t.Error("Last .pvk-content should contain .footer.")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestLastEmpty(t *testing.T) {
|
||||||
|
sel := Doc().Find(".pvk-zzcontentzz").Last()
|
||||||
|
assertLength(t, sel.Nodes, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestLastRollback(t *testing.T) {
|
||||||
|
sel := Doc().Find(".pvk-content")
|
||||||
|
sel2 := sel.Last().End()
|
||||||
|
assertEqual(t, sel, sel2)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestEq(t *testing.T) {
|
||||||
|
sel := Doc().Find(".pvk-content").Eq(1)
|
||||||
|
assertLength(t, sel.Nodes, 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestEqNegative(t *testing.T) {
|
||||||
|
sel := Doc().Find(".pvk-content").Eq(-1)
|
||||||
|
assertLength(t, sel.Nodes, 1)
|
||||||
|
|
||||||
|
// Should contain Footer
|
||||||
|
foot := Doc().Find(".footer")
|
||||||
|
if !sel.Contains(foot.Nodes[0]) {
|
||||||
|
t.Error("Index -1 of .pvk-content should contain .footer.")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestEqEmpty(t *testing.T) {
|
||||||
|
sel := Doc().Find("something_random_that_does_not_exists").Eq(0)
|
||||||
|
assertLength(t, sel.Nodes, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestEqInvalidPositive(t *testing.T) {
|
||||||
|
sel := Doc().Find(".pvk-content").Eq(3)
|
||||||
|
assertLength(t, sel.Nodes, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestEqInvalidNegative(t *testing.T) {
|
||||||
|
sel := Doc().Find(".pvk-content").Eq(-4)
|
||||||
|
assertLength(t, sel.Nodes, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestEqRollback(t *testing.T) {
|
||||||
|
sel := Doc().Find(".pvk-content")
|
||||||
|
sel2 := sel.Eq(1).End()
|
||||||
|
assertEqual(t, sel, sel2)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSlice(t *testing.T) {
|
||||||
|
sel := Doc().Find(".pvk-content").Slice(0, 2)
|
||||||
|
|
||||||
|
assertLength(t, sel.Nodes, 2)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSliceOutOfBounds(t *testing.T) {
|
||||||
|
defer assertPanic(t)
|
||||||
|
Doc().Find(".pvk-content").Slice(2, 12)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestNegativeSliceStart(t *testing.T) {
|
||||||
|
sel := Doc().Find(".container-fluid").Slice(-2, 3)
|
||||||
|
assertLength(t, sel.Nodes, 1)
|
||||||
|
assertSelectionIs(t, sel.Eq(0), "#cf3")
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestNegativeSliceEnd(t *testing.T) {
|
||||||
|
sel := Doc().Find(".container-fluid").Slice(1, -1)
|
||||||
|
assertLength(t, sel.Nodes, 2)
|
||||||
|
assertSelectionIs(t, sel.Eq(0), "#cf2")
|
||||||
|
assertSelectionIs(t, sel.Eq(1), "#cf3")
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestNegativeSliceBoth(t *testing.T) {
|
||||||
|
sel := Doc().Find(".container-fluid").Slice(-3, -1)
|
||||||
|
assertLength(t, sel.Nodes, 2)
|
||||||
|
assertSelectionIs(t, sel.Eq(0), "#cf2")
|
||||||
|
assertSelectionIs(t, sel.Eq(1), "#cf3")
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestNegativeSliceOutOfBounds(t *testing.T) {
|
||||||
|
defer assertPanic(t)
|
||||||
|
Doc().Find(".container-fluid").Slice(-12, -7)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSliceRollback(t *testing.T) {
|
||||||
|
sel := Doc().Find(".pvk-content")
|
||||||
|
sel2 := sel.Slice(0, 2).End()
|
||||||
|
assertEqual(t, sel, sel2)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestGet(t *testing.T) {
|
||||||
|
sel := Doc().Find(".pvk-content")
|
||||||
|
node := sel.Get(1)
|
||||||
|
if sel.Nodes[1] != node {
|
||||||
|
t.Errorf("Expected node %v to be %v.", node, sel.Nodes[1])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestGetNegative(t *testing.T) {
|
||||||
|
sel := Doc().Find(".pvk-content")
|
||||||
|
node := sel.Get(-3)
|
||||||
|
if sel.Nodes[0] != node {
|
||||||
|
t.Errorf("Expected node %v to be %v.", node, sel.Nodes[0])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestGetInvalid(t *testing.T) {
|
||||||
|
defer assertPanic(t)
|
||||||
|
sel := Doc().Find(".pvk-content")
|
||||||
|
sel.Get(129)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestIndex(t *testing.T) {
|
||||||
|
sel := Doc().Find(".pvk-content")
|
||||||
|
if i := sel.Index(); i != 1 {
|
||||||
|
t.Errorf("Expected index of 1, got %v.", i)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestIndexSelector(t *testing.T) {
|
||||||
|
sel := Doc().Find(".hero-unit")
|
||||||
|
if i := sel.IndexSelector("div"); i != 4 {
|
||||||
|
t.Errorf("Expected index of 4, got %v.", i)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestIndexOfNode(t *testing.T) {
|
||||||
|
sel := Doc().Find("div.pvk-gutter")
|
||||||
|
if i := sel.IndexOfNode(sel.Nodes[1]); i != 1 {
|
||||||
|
t.Errorf("Expected index of 1, got %v.", i)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestIndexOfNilNode(t *testing.T) {
|
||||||
|
sel := Doc().Find("div.pvk-gutter")
|
||||||
|
if i := sel.IndexOfNode(nil); i != -1 {
|
||||||
|
t.Errorf("Expected index of -1, got %v.", i)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestIndexOfSelection(t *testing.T) {
|
||||||
|
sel := Doc().Find("div")
|
||||||
|
sel2 := Doc().Find(".hero-unit")
|
||||||
|
if i := sel.IndexOfSelection(sel2); i != 4 {
|
||||||
|
t.Errorf("Expected index of 4, got %v.", i)
|
||||||
|
}
|
||||||
|
}
|
436
Godeps/_workspace/src/github.com/PuerkitoBio/goquery/bench/v0.1.0
generated
vendored
Normal file
436
Godeps/_workspace/src/github.com/PuerkitoBio/goquery/bench/v0.1.0
generated
vendored
Normal file
|
@ -0,0 +1,436 @@
|
||||||
|
PASS
|
||||||
|
BenchmarkFirst 20000000 92.9 ns/op
|
||||||
|
BenchmarkLast 20000000 91.6 ns/op
|
||||||
|
BenchmarkEq 20000000 90.6 ns/op
|
||||||
|
BenchmarkSlice 20000000 86.7 ns/op
|
||||||
|
BenchmarkGet 1000000000 2.14 ns/op
|
||||||
|
BenchmarkIndex 500000 5308 ns/op
|
||||||
|
--- BENCH: BenchmarkIndex
|
||||||
|
bench_array_test.go:73: Index=3
|
||||||
|
bench_array_test.go:73: Index=3
|
||||||
|
bench_array_test.go:73: Index=3
|
||||||
|
bench_array_test.go:73: Index=3
|
||||||
|
BenchmarkIndexSelector 50000 54962 ns/op
|
||||||
|
--- BENCH: BenchmarkIndexSelector
|
||||||
|
bench_array_test.go:85: IndexSelector=4
|
||||||
|
bench_array_test.go:85: IndexSelector=4
|
||||||
|
bench_array_test.go:85: IndexSelector=4
|
||||||
|
bench_array_test.go:85: IndexSelector=4
|
||||||
|
BenchmarkIndexOfNode 100000000 11.4 ns/op
|
||||||
|
--- BENCH: BenchmarkIndexOfNode
|
||||||
|
bench_array_test.go:99: IndexOfNode=2
|
||||||
|
bench_array_test.go:99: IndexOfNode=2
|
||||||
|
bench_array_test.go:99: IndexOfNode=2
|
||||||
|
bench_array_test.go:99: IndexOfNode=2
|
||||||
|
bench_array_test.go:99: IndexOfNode=2
|
||||||
|
BenchmarkIndexOfSelection 100000000 12.1 ns/op
|
||||||
|
--- BENCH: BenchmarkIndexOfSelection
|
||||||
|
bench_array_test.go:111: IndexOfSelection=2
|
||||||
|
bench_array_test.go:111: IndexOfSelection=2
|
||||||
|
bench_array_test.go:111: IndexOfSelection=2
|
||||||
|
bench_array_test.go:111: IndexOfSelection=2
|
||||||
|
bench_array_test.go:111: IndexOfSelection=2
|
||||||
|
BenchmarkMetalReviewExample 5000 327144 ns/op
|
||||||
|
--- BENCH: BenchmarkMetalReviewExample
|
||||||
|
bench_example_test.go:40: Review 0: Midnight - Complete and Total Hell (8.5).
|
||||||
|
Review 1: Over Your Threshold - Facticity (6.0).
|
||||||
|
Review 2: Nuclear Death Terror - Chaos Reigns (7.5).
|
||||||
|
Review 3: Evoken - Atra Mors (9.5).
|
||||||
|
|
||||||
|
bench_example_test.go:41: MetalReviewExample=10
|
||||||
|
bench_example_test.go:40: Review 0: Midnight - Complete and Total Hell (8.5).
|
||||||
|
Review 1: Over Your Threshold - Facticity (6.0).
|
||||||
|
Review 2: Nuclear Death Terror - Chaos Reigns (7.5).
|
||||||
|
Review 3: Evoken - Atra Mors (9.5).
|
||||||
|
... [output truncated]
|
||||||
|
BenchmarkAdd 50000 52945 ns/op
|
||||||
|
--- BENCH: BenchmarkAdd
|
||||||
|
bench_expand_test.go:20: Add=43
|
||||||
|
bench_expand_test.go:20: Add=43
|
||||||
|
bench_expand_test.go:20: Add=43
|
||||||
|
bench_expand_test.go:20: Add=43
|
||||||
|
BenchmarkAddSelection 10000000 205 ns/op
|
||||||
|
--- BENCH: BenchmarkAddSelection
|
||||||
|
bench_expand_test.go:37: AddSelection=43
|
||||||
|
bench_expand_test.go:37: AddSelection=43
|
||||||
|
bench_expand_test.go:37: AddSelection=43
|
||||||
|
bench_expand_test.go:37: AddSelection=43
|
||||||
|
bench_expand_test.go:37: AddSelection=43
|
||||||
|
BenchmarkAddNodes 10000000 203 ns/op
|
||||||
|
--- BENCH: BenchmarkAddNodes
|
||||||
|
bench_expand_test.go:55: AddNodes=43
|
||||||
|
bench_expand_test.go:55: AddNodes=43
|
||||||
|
bench_expand_test.go:55: AddNodes=43
|
||||||
|
bench_expand_test.go:55: AddNodes=43
|
||||||
|
bench_expand_test.go:55: AddNodes=43
|
||||||
|
BenchmarkAndSelf 1000000 2639 ns/op
|
||||||
|
--- BENCH: BenchmarkAndSelf
|
||||||
|
bench_expand_test.go:71: AndSelf=44
|
||||||
|
bench_expand_test.go:71: AndSelf=44
|
||||||
|
bench_expand_test.go:71: AndSelf=44
|
||||||
|
bench_expand_test.go:71: AndSelf=44
|
||||||
|
BenchmarkFilter 50000 30182 ns/op
|
||||||
|
--- BENCH: BenchmarkFilter
|
||||||
|
bench_filter_test.go:20: Filter=13
|
||||||
|
bench_filter_test.go:20: Filter=13
|
||||||
|
bench_filter_test.go:20: Filter=13
|
||||||
|
bench_filter_test.go:20: Filter=13
|
||||||
|
BenchmarkNot 50000 34855 ns/op
|
||||||
|
--- BENCH: BenchmarkNot
|
||||||
|
bench_filter_test.go:36: Not=371
|
||||||
|
bench_filter_test.go:36: Not=371
|
||||||
|
bench_filter_test.go:36: Not=371
|
||||||
|
bench_filter_test.go:36: Not=371
|
||||||
|
BenchmarkFilterFunction 50000 66052 ns/op
|
||||||
|
--- BENCH: BenchmarkFilterFunction
|
||||||
|
bench_filter_test.go:55: FilterFunction=112
|
||||||
|
bench_filter_test.go:55: FilterFunction=112
|
||||||
|
bench_filter_test.go:55: FilterFunction=112
|
||||||
|
bench_filter_test.go:55: FilterFunction=112
|
||||||
|
BenchmarkNotFunction 50000 69721 ns/op
|
||||||
|
--- BENCH: BenchmarkNotFunction
|
||||||
|
bench_filter_test.go:74: NotFunction=261
|
||||||
|
bench_filter_test.go:74: NotFunction=261
|
||||||
|
bench_filter_test.go:74: NotFunction=261
|
||||||
|
bench_filter_test.go:74: NotFunction=261
|
||||||
|
BenchmarkFilterNodes 50000 66077 ns/op
|
||||||
|
--- BENCH: BenchmarkFilterNodes
|
||||||
|
bench_filter_test.go:92: FilterNodes=2
|
||||||
|
bench_filter_test.go:92: FilterNodes=2
|
||||||
|
bench_filter_test.go:92: FilterNodes=2
|
||||||
|
bench_filter_test.go:92: FilterNodes=2
|
||||||
|
BenchmarkNotNodes 20000 80021 ns/op
|
||||||
|
--- BENCH: BenchmarkNotNodes
|
||||||
|
bench_filter_test.go:110: NotNodes=360
|
||||||
|
bench_filter_test.go:110: NotNodes=360
|
||||||
|
bench_filter_test.go:110: NotNodes=360
|
||||||
|
bench_filter_test.go:110: NotNodes=360
|
||||||
|
BenchmarkFilterSelection 50000 66256 ns/op
|
||||||
|
--- BENCH: BenchmarkFilterSelection
|
||||||
|
bench_filter_test.go:127: FilterSelection=2
|
||||||
|
bench_filter_test.go:127: FilterSelection=2
|
||||||
|
bench_filter_test.go:127: FilterSelection=2
|
||||||
|
bench_filter_test.go:127: FilterSelection=2
|
||||||
|
BenchmarkNotSelection 20000 79568 ns/op
|
||||||
|
--- BENCH: BenchmarkNotSelection
|
||||||
|
bench_filter_test.go:144: NotSelection=360
|
||||||
|
bench_filter_test.go:144: NotSelection=360
|
||||||
|
bench_filter_test.go:144: NotSelection=360
|
||||||
|
bench_filter_test.go:144: NotSelection=360
|
||||||
|
BenchmarkHas 5000 569441 ns/op
|
||||||
|
--- BENCH: BenchmarkHas
|
||||||
|
bench_filter_test.go:160: Has=13
|
||||||
|
bench_filter_test.go:160: Has=13
|
||||||
|
bench_filter_test.go:160: Has=13
|
||||||
|
BenchmarkHasNodes 10000 230585 ns/op
|
||||||
|
--- BENCH: BenchmarkHasNodes
|
||||||
|
bench_filter_test.go:178: HasNodes=15
|
||||||
|
bench_filter_test.go:178: HasNodes=15
|
||||||
|
bench_filter_test.go:178: HasNodes=15
|
||||||
|
BenchmarkHasSelection 10000 231470 ns/op
|
||||||
|
--- BENCH: BenchmarkHasSelection
|
||||||
|
bench_filter_test.go:195: HasSelection=15
|
||||||
|
bench_filter_test.go:195: HasSelection=15
|
||||||
|
bench_filter_test.go:195: HasSelection=15
|
||||||
|
BenchmarkEnd 500000000 4.65 ns/op
|
||||||
|
--- BENCH: BenchmarkEnd
|
||||||
|
bench_filter_test.go:211: End=373
|
||||||
|
bench_filter_test.go:211: End=373
|
||||||
|
bench_filter_test.go:211: End=373
|
||||||
|
bench_filter_test.go:211: End=373
|
||||||
|
bench_filter_test.go:211: End=373
|
||||||
|
bench_filter_test.go:211: End=373
|
||||||
|
BenchmarkEach 200000 9558 ns/op
|
||||||
|
--- BENCH: BenchmarkEach
|
||||||
|
bench_iteration_test.go:22: Each=59
|
||||||
|
bench_iteration_test.go:22: Each=59
|
||||||
|
bench_iteration_test.go:22: Each=59
|
||||||
|
bench_iteration_test.go:22: Each=59
|
||||||
|
BenchmarkMap 100000 16809 ns/op
|
||||||
|
--- BENCH: BenchmarkMap
|
||||||
|
bench_iteration_test.go:41: Map=59
|
||||||
|
bench_iteration_test.go:41: Map=59
|
||||||
|
bench_iteration_test.go:41: Map=59
|
||||||
|
bench_iteration_test.go:41: Map=59
|
||||||
|
BenchmarkAttr 50000000 37.5 ns/op
|
||||||
|
--- BENCH: BenchmarkAttr
|
||||||
|
bench_property_test.go:16: Attr=firstHeading
|
||||||
|
bench_property_test.go:16: Attr=firstHeading
|
||||||
|
bench_property_test.go:16: Attr=firstHeading
|
||||||
|
bench_property_test.go:16: Attr=firstHeading
|
||||||
|
bench_property_test.go:16: Attr=firstHeading
|
||||||
|
BenchmarkText 100000 18583 ns/op
|
||||||
|
BenchmarkLength 2000000000 0.80 ns/op
|
||||||
|
--- BENCH: BenchmarkLength
|
||||||
|
bench_property_test.go:37: Length=14
|
||||||
|
bench_property_test.go:37: Length=14
|
||||||
|
bench_property_test.go:37: Length=14
|
||||||
|
bench_property_test.go:37: Length=14
|
||||||
|
bench_property_test.go:37: Length=14
|
||||||
|
bench_property_test.go:37: Length=14
|
||||||
|
BenchmarkHtml 5000000 666 ns/op
|
||||||
|
BenchmarkIs 50000 34328 ns/op
|
||||||
|
--- BENCH: BenchmarkIs
|
||||||
|
bench_query_test.go:16: Is=true
|
||||||
|
bench_query_test.go:16: Is=true
|
||||||
|
bench_query_test.go:16: Is=true
|
||||||
|
bench_query_test.go:16: Is=true
|
||||||
|
BenchmarkIsPositional 50000 32423 ns/op
|
||||||
|
--- BENCH: BenchmarkIsPositional
|
||||||
|
bench_query_test.go:28: IsPositional=true
|
||||||
|
bench_query_test.go:28: IsPositional=true
|
||||||
|
bench_query_test.go:28: IsPositional=true
|
||||||
|
bench_query_test.go:28: IsPositional=true
|
||||||
|
BenchmarkIsFunction 1000000 2707 ns/op
|
||||||
|
--- BENCH: BenchmarkIsFunction
|
||||||
|
bench_query_test.go:43: IsFunction=true
|
||||||
|
bench_query_test.go:43: IsFunction=true
|
||||||
|
bench_query_test.go:43: IsFunction=true
|
||||||
|
bench_query_test.go:43: IsFunction=true
|
||||||
|
BenchmarkIsSelection 50000 66976 ns/op
|
||||||
|
--- BENCH: BenchmarkIsSelection
|
||||||
|
bench_query_test.go:56: IsSelection=true
|
||||||
|
bench_query_test.go:56: IsSelection=true
|
||||||
|
bench_query_test.go:56: IsSelection=true
|
||||||
|
bench_query_test.go:56: IsSelection=true
|
||||||
|
BenchmarkIsNodes 50000 66740 ns/op
|
||||||
|
--- BENCH: BenchmarkIsNodes
|
||||||
|
bench_query_test.go:70: IsNodes=true
|
||||||
|
bench_query_test.go:70: IsNodes=true
|
||||||
|
bench_query_test.go:70: IsNodes=true
|
||||||
|
bench_query_test.go:70: IsNodes=true
|
||||||
|
BenchmarkHasClass 5000 701722 ns/op
|
||||||
|
--- BENCH: BenchmarkHasClass
|
||||||
|
bench_query_test.go:82: HasClass=true
|
||||||
|
bench_query_test.go:82: HasClass=true
|
||||||
|
bench_query_test.go:82: HasClass=true
|
||||||
|
BenchmarkContains 100000000 11.9 ns/op
|
||||||
|
--- BENCH: BenchmarkContains
|
||||||
|
bench_query_test.go:96: Contains=true
|
||||||
|
bench_query_test.go:96: Contains=true
|
||||||
|
bench_query_test.go:96: Contains=true
|
||||||
|
bench_query_test.go:96: Contains=true
|
||||||
|
bench_query_test.go:96: Contains=true
|
||||||
|
BenchmarkFind 50000 55444 ns/op
|
||||||
|
--- BENCH: BenchmarkFind
|
||||||
|
bench_traversal_test.go:18: Find=41
|
||||||
|
bench_traversal_test.go:18: Find=41
|
||||||
|
bench_traversal_test.go:18: Find=41
|
||||||
|
bench_traversal_test.go:18: Find=41
|
||||||
|
BenchmarkFindWithinSelection 10000 127984 ns/op
|
||||||
|
--- BENCH: BenchmarkFindWithinSelection
|
||||||
|
bench_traversal_test.go:34: FindWithinSelection=39
|
||||||
|
bench_traversal_test.go:34: FindWithinSelection=39
|
||||||
|
bench_traversal_test.go:34: FindWithinSelection=39
|
||||||
|
BenchmarkFindSelection 5000 355944 ns/op
|
||||||
|
--- BENCH: BenchmarkFindSelection
|
||||||
|
bench_traversal_test.go:51: FindSelection=73
|
||||||
|
bench_traversal_test.go:51: FindSelection=73
|
||||||
|
bench_traversal_test.go:51: FindSelection=73
|
||||||
|
BenchmarkFindNodes 5000 355596 ns/op
|
||||||
|
--- BENCH: BenchmarkFindNodes
|
||||||
|
bench_traversal_test.go:69: FindNodes=73
|
||||||
|
bench_traversal_test.go:69: FindNodes=73
|
||||||
|
bench_traversal_test.go:69: FindNodes=73
|
||||||
|
BenchmarkContents 500000 5656 ns/op
|
||||||
|
--- BENCH: BenchmarkContents
|
||||||
|
bench_traversal_test.go:85: Contents=16
|
||||||
|
bench_traversal_test.go:85: Contents=16
|
||||||
|
bench_traversal_test.go:85: Contents=16
|
||||||
|
bench_traversal_test.go:85: Contents=16
|
||||||
|
BenchmarkContentsFiltered 200000 9007 ns/op
|
||||||
|
--- BENCH: BenchmarkContentsFiltered
|
||||||
|
bench_traversal_test.go:101: ContentsFiltered=1
|
||||||
|
bench_traversal_test.go:101: ContentsFiltered=1
|
||||||
|
bench_traversal_test.go:101: ContentsFiltered=1
|
||||||
|
bench_traversal_test.go:101: ContentsFiltered=1
|
||||||
|
BenchmarkChildren 1000000 1237 ns/op
|
||||||
|
--- BENCH: BenchmarkChildren
|
||||||
|
bench_traversal_test.go:117: Children=2
|
||||||
|
bench_traversal_test.go:117: Children=2
|
||||||
|
bench_traversal_test.go:117: Children=2
|
||||||
|
bench_traversal_test.go:117: Children=2
|
||||||
|
BenchmarkChildrenFiltered 500000 5613 ns/op
|
||||||
|
--- BENCH: BenchmarkChildrenFiltered
|
||||||
|
bench_traversal_test.go:133: ChildrenFiltered=2
|
||||||
|
bench_traversal_test.go:133: ChildrenFiltered=2
|
||||||
|
bench_traversal_test.go:133: ChildrenFiltered=2
|
||||||
|
bench_traversal_test.go:133: ChildrenFiltered=2
|
||||||
|
BenchmarkParent 50000 47026 ns/op
|
||||||
|
--- BENCH: BenchmarkParent
|
||||||
|
bench_traversal_test.go:149: Parent=55
|
||||||
|
bench_traversal_test.go:149: Parent=55
|
||||||
|
bench_traversal_test.go:149: Parent=55
|
||||||
|
bench_traversal_test.go:149: Parent=55
|
||||||
|
BenchmarkParentFiltered 50000 51438 ns/op
|
||||||
|
--- BENCH: BenchmarkParentFiltered
|
||||||
|
bench_traversal_test.go:165: ParentFiltered=4
|
||||||
|
bench_traversal_test.go:165: ParentFiltered=4
|
||||||
|
bench_traversal_test.go:165: ParentFiltered=4
|
||||||
|
bench_traversal_test.go:165: ParentFiltered=4
|
||||||
|
BenchmarkParents 20000 91820 ns/op
|
||||||
|
--- BENCH: BenchmarkParents
|
||||||
|
bench_traversal_test.go:181: Parents=73
|
||||||
|
bench_traversal_test.go:181: Parents=73
|
||||||
|
bench_traversal_test.go:181: Parents=73
|
||||||
|
bench_traversal_test.go:181: Parents=73
|
||||||
|
BenchmarkParentsFiltered 20000 95156 ns/op
|
||||||
|
--- BENCH: BenchmarkParentsFiltered
|
||||||
|
bench_traversal_test.go:197: ParentsFiltered=18
|
||||||
|
bench_traversal_test.go:197: ParentsFiltered=18
|
||||||
|
bench_traversal_test.go:197: ParentsFiltered=18
|
||||||
|
bench_traversal_test.go:197: ParentsFiltered=18
|
||||||
|
BenchmarkParentsUntil 10000 134383 ns/op
|
||||||
|
--- BENCH: BenchmarkParentsUntil
|
||||||
|
bench_traversal_test.go:213: ParentsUntil=52
|
||||||
|
bench_traversal_test.go:213: ParentsUntil=52
|
||||||
|
bench_traversal_test.go:213: ParentsUntil=52
|
||||||
|
BenchmarkParentsUntilSelection 10000 235456 ns/op
|
||||||
|
--- BENCH: BenchmarkParentsUntilSelection
|
||||||
|
bench_traversal_test.go:230: ParentsUntilSelection=70
|
||||||
|
bench_traversal_test.go:230: ParentsUntilSelection=70
|
||||||
|
bench_traversal_test.go:230: ParentsUntilSelection=70
|
||||||
|
BenchmarkParentsUntilNodes 10000 235936 ns/op
|
||||||
|
--- BENCH: BenchmarkParentsUntilNodes
|
||||||
|
bench_traversal_test.go:248: ParentsUntilNodes=70
|
||||||
|
bench_traversal_test.go:248: ParentsUntilNodes=70
|
||||||
|
bench_traversal_test.go:248: ParentsUntilNodes=70
|
||||||
|
BenchmarkParentsFilteredUntil 50000 32451 ns/op
|
||||||
|
--- BENCH: BenchmarkParentsFilteredUntil
|
||||||
|
bench_traversal_test.go:264: ParentsFilteredUntil=2
|
||||||
|
bench_traversal_test.go:264: ParentsFilteredUntil=2
|
||||||
|
bench_traversal_test.go:264: ParentsFilteredUntil=2
|
||||||
|
bench_traversal_test.go:264: ParentsFilteredUntil=2
|
||||||
|
BenchmarkParentsFilteredUntilSelection 50000 30570 ns/op
|
||||||
|
--- BENCH: BenchmarkParentsFilteredUntilSelection
|
||||||
|
bench_traversal_test.go:281: ParentsFilteredUntilSelection=2
|
||||||
|
bench_traversal_test.go:281: ParentsFilteredUntilSelection=2
|
||||||
|
bench_traversal_test.go:281: ParentsFilteredUntilSelection=2
|
||||||
|
bench_traversal_test.go:281: ParentsFilteredUntilSelection=2
|
||||||
|
BenchmarkParentsFilteredUntilNodes 50000 30729 ns/op
|
||||||
|
--- BENCH: BenchmarkParentsFilteredUntilNodes
|
||||||
|
bench_traversal_test.go:299: ParentsFilteredUntilNodes=2
|
||||||
|
bench_traversal_test.go:299: ParentsFilteredUntilNodes=2
|
||||||
|
bench_traversal_test.go:299: ParentsFilteredUntilNodes=2
|
||||||
|
bench_traversal_test.go:299: ParentsFilteredUntilNodes=2
|
||||||
|
BenchmarkSiblings 10000 106704 ns/op
|
||||||
|
--- BENCH: BenchmarkSiblings
|
||||||
|
bench_traversal_test.go:315: Siblings=293
|
||||||
|
bench_traversal_test.go:315: Siblings=293
|
||||||
|
bench_traversal_test.go:315: Siblings=293
|
||||||
|
BenchmarkSiblingsFiltered 10000 115592 ns/op
|
||||||
|
--- BENCH: BenchmarkSiblingsFiltered
|
||||||
|
bench_traversal_test.go:331: SiblingsFiltered=46
|
||||||
|
bench_traversal_test.go:331: SiblingsFiltered=46
|
||||||
|
bench_traversal_test.go:331: SiblingsFiltered=46
|
||||||
|
BenchmarkNext 50000 54449 ns/op
|
||||||
|
--- BENCH: BenchmarkNext
|
||||||
|
bench_traversal_test.go:347: Next=49
|
||||||
|
bench_traversal_test.go:347: Next=49
|
||||||
|
bench_traversal_test.go:347: Next=49
|
||||||
|
bench_traversal_test.go:347: Next=49
|
||||||
|
BenchmarkNextFiltered 50000 58503 ns/op
|
||||||
|
--- BENCH: BenchmarkNextFiltered
|
||||||
|
bench_traversal_test.go:363: NextFiltered=6
|
||||||
|
bench_traversal_test.go:363: NextFiltered=6
|
||||||
|
bench_traversal_test.go:363: NextFiltered=6
|
||||||
|
bench_traversal_test.go:363: NextFiltered=6
|
||||||
|
BenchmarkNextAll 20000 77698 ns/op
|
||||||
|
--- BENCH: BenchmarkNextAll
|
||||||
|
bench_traversal_test.go:379: NextAll=234
|
||||||
|
bench_traversal_test.go:379: NextAll=234
|
||||||
|
bench_traversal_test.go:379: NextAll=234
|
||||||
|
bench_traversal_test.go:379: NextAll=234
|
||||||
|
BenchmarkNextAllFiltered 20000 85034 ns/op
|
||||||
|
--- BENCH: BenchmarkNextAllFiltered
|
||||||
|
bench_traversal_test.go:395: NextAllFiltered=33
|
||||||
|
bench_traversal_test.go:395: NextAllFiltered=33
|
||||||
|
bench_traversal_test.go:395: NextAllFiltered=33
|
||||||
|
bench_traversal_test.go:395: NextAllFiltered=33
|
||||||
|
BenchmarkPrev 50000 56458 ns/op
|
||||||
|
--- BENCH: BenchmarkPrev
|
||||||
|
bench_traversal_test.go:411: Prev=49
|
||||||
|
bench_traversal_test.go:411: Prev=49
|
||||||
|
bench_traversal_test.go:411: Prev=49
|
||||||
|
bench_traversal_test.go:411: Prev=49
|
||||||
|
BenchmarkPrevFiltered 50000 60163 ns/op
|
||||||
|
--- BENCH: BenchmarkPrevFiltered
|
||||||
|
bench_traversal_test.go:429: PrevFiltered=7
|
||||||
|
bench_traversal_test.go:429: PrevFiltered=7
|
||||||
|
bench_traversal_test.go:429: PrevFiltered=7
|
||||||
|
bench_traversal_test.go:429: PrevFiltered=7
|
||||||
|
BenchmarkPrevAll 50000 47679 ns/op
|
||||||
|
--- BENCH: BenchmarkPrevAll
|
||||||
|
bench_traversal_test.go:445: PrevAll=78
|
||||||
|
bench_traversal_test.go:445: PrevAll=78
|
||||||
|
bench_traversal_test.go:445: PrevAll=78
|
||||||
|
bench_traversal_test.go:445: PrevAll=78
|
||||||
|
BenchmarkPrevAllFiltered 50000 51563 ns/op
|
||||||
|
--- BENCH: BenchmarkPrevAllFiltered
|
||||||
|
bench_traversal_test.go:461: PrevAllFiltered=6
|
||||||
|
bench_traversal_test.go:461: PrevAllFiltered=6
|
||||||
|
bench_traversal_test.go:461: PrevAllFiltered=6
|
||||||
|
bench_traversal_test.go:461: PrevAllFiltered=6
|
||||||
|
BenchmarkNextUntil 10000 213998 ns/op
|
||||||
|
--- BENCH: BenchmarkNextUntil
|
||||||
|
bench_traversal_test.go:477: NextUntil=84
|
||||||
|
bench_traversal_test.go:477: NextUntil=84
|
||||||
|
bench_traversal_test.go:477: NextUntil=84
|
||||||
|
BenchmarkNextUntilSelection 10000 140720 ns/op
|
||||||
|
--- BENCH: BenchmarkNextUntilSelection
|
||||||
|
bench_traversal_test.go:494: NextUntilSelection=42
|
||||||
|
bench_traversal_test.go:494: NextUntilSelection=42
|
||||||
|
bench_traversal_test.go:494: NextUntilSelection=42
|
||||||
|
BenchmarkNextUntilNodes 20000 90702 ns/op
|
||||||
|
--- BENCH: BenchmarkNextUntilNodes
|
||||||
|
bench_traversal_test.go:512: NextUntilNodes=12
|
||||||
|
bench_traversal_test.go:512: NextUntilNodes=12
|
||||||
|
bench_traversal_test.go:512: NextUntilNodes=12
|
||||||
|
bench_traversal_test.go:512: NextUntilNodes=12
|
||||||
|
BenchmarkPrevUntil 5000 456039 ns/op
|
||||||
|
--- BENCH: BenchmarkPrevUntil
|
||||||
|
bench_traversal_test.go:528: PrevUntil=238
|
||||||
|
bench_traversal_test.go:528: PrevUntil=238
|
||||||
|
bench_traversal_test.go:528: PrevUntil=238
|
||||||
|
BenchmarkPrevUntilSelection 10000 167944 ns/op
|
||||||
|
--- BENCH: BenchmarkPrevUntilSelection
|
||||||
|
bench_traversal_test.go:545: PrevUntilSelection=49
|
||||||
|
bench_traversal_test.go:545: PrevUntilSelection=49
|
||||||
|
bench_traversal_test.go:545: PrevUntilSelection=49
|
||||||
|
BenchmarkPrevUntilNodes 20000 82059 ns/op
|
||||||
|
--- BENCH: BenchmarkPrevUntilNodes
|
||||||
|
bench_traversal_test.go:563: PrevUntilNodes=11
|
||||||
|
bench_traversal_test.go:563: PrevUntilNodes=11
|
||||||
|
bench_traversal_test.go:563: PrevUntilNodes=11
|
||||||
|
bench_traversal_test.go:563: PrevUntilNodes=11
|
||||||
|
BenchmarkNextFilteredUntil 10000 150883 ns/op
|
||||||
|
--- BENCH: BenchmarkNextFilteredUntil
|
||||||
|
bench_traversal_test.go:579: NextFilteredUntil=22
|
||||||
|
bench_traversal_test.go:579: NextFilteredUntil=22
|
||||||
|
bench_traversal_test.go:579: NextFilteredUntil=22
|
||||||
|
BenchmarkNextFilteredUntilSelection 10000 146578 ns/op
|
||||||
|
--- BENCH: BenchmarkNextFilteredUntilSelection
|
||||||
|
bench_traversal_test.go:596: NextFilteredUntilSelection=22
|
||||||
|
bench_traversal_test.go:596: NextFilteredUntilSelection=22
|
||||||
|
bench_traversal_test.go:596: NextFilteredUntilSelection=22
|
||||||
|
BenchmarkNextFilteredUntilNodes 10000 148284 ns/op
|
||||||
|
--- BENCH: BenchmarkNextFilteredUntilNodes
|
||||||
|
bench_traversal_test.go:614: NextFilteredUntilNodes=22
|
||||||
|
bench_traversal_test.go:614: NextFilteredUntilNodes=22
|
||||||
|
bench_traversal_test.go:614: NextFilteredUntilNodes=22
|
||||||
|
BenchmarkPrevFilteredUntil 10000 154303 ns/op
|
||||||
|
--- BENCH: BenchmarkPrevFilteredUntil
|
||||||
|
bench_traversal_test.go:630: PrevFilteredUntil=20
|
||||||
|
bench_traversal_test.go:630: PrevFilteredUntil=20
|
||||||
|
bench_traversal_test.go:630: PrevFilteredUntil=20
|
||||||
|
BenchmarkPrevFilteredUntilSelection 10000 149062 ns/op
|
||||||
|
--- BENCH: BenchmarkPrevFilteredUntilSelection
|
||||||
|
bench_traversal_test.go:647: PrevFilteredUntilSelection=20
|
||||||
|
bench_traversal_test.go:647: PrevFilteredUntilSelection=20
|
||||||
|
bench_traversal_test.go:647: PrevFilteredUntilSelection=20
|
||||||
|
BenchmarkPrevFilteredUntilNodes 10000 150584 ns/op
|
||||||
|
--- BENCH: BenchmarkPrevFilteredUntilNodes
|
||||||
|
bench_traversal_test.go:665: PrevFilteredUntilNodes=20
|
||||||
|
bench_traversal_test.go:665: PrevFilteredUntilNodes=20
|
||||||
|
bench_traversal_test.go:665: PrevFilteredUntilNodes=20
|
||||||
|
ok github.com/PuerkitoBio/goquery 188.326s
|
438
Godeps/_workspace/src/github.com/PuerkitoBio/goquery/bench/v0.1.1
generated
vendored
Normal file
438
Godeps/_workspace/src/github.com/PuerkitoBio/goquery/bench/v0.1.1
generated
vendored
Normal file
|
@ -0,0 +1,438 @@
|
||||||
|
PASS
|
||||||
|
BenchmarkFirst 20000000 96.2 ns/op
|
||||||
|
BenchmarkLast 20000000 95.8 ns/op
|
||||||
|
BenchmarkEq 20000000 94.4 ns/op
|
||||||
|
BenchmarkSlice 20000000 89.9 ns/op
|
||||||
|
BenchmarkGet 1000000000 2.31 ns/op
|
||||||
|
BenchmarkIndex 1000000 1911 ns/op
|
||||||
|
--- BENCH: BenchmarkIndex
|
||||||
|
bench_array_test.go:73: Index=3
|
||||||
|
bench_array_test.go:73: Index=3
|
||||||
|
bench_array_test.go:73: Index=3
|
||||||
|
bench_array_test.go:73: Index=3
|
||||||
|
BenchmarkIndexSelector 50000 56034 ns/op
|
||||||
|
--- BENCH: BenchmarkIndexSelector
|
||||||
|
bench_array_test.go:85: IndexSelector=4
|
||||||
|
bench_array_test.go:85: IndexSelector=4
|
||||||
|
bench_array_test.go:85: IndexSelector=4
|
||||||
|
bench_array_test.go:85: IndexSelector=4
|
||||||
|
BenchmarkIndexOfNode 100000000 11.8 ns/op
|
||||||
|
--- BENCH: BenchmarkIndexOfNode
|
||||||
|
bench_array_test.go:99: IndexOfNode=2
|
||||||
|
bench_array_test.go:99: IndexOfNode=2
|
||||||
|
bench_array_test.go:99: IndexOfNode=2
|
||||||
|
bench_array_test.go:99: IndexOfNode=2
|
||||||
|
bench_array_test.go:99: IndexOfNode=2
|
||||||
|
BenchmarkIndexOfSelection 100000000 12.1 ns/op
|
||||||
|
--- BENCH: BenchmarkIndexOfSelection
|
||||||
|
bench_array_test.go:111: IndexOfSelection=2
|
||||||
|
bench_array_test.go:111: IndexOfSelection=2
|
||||||
|
bench_array_test.go:111: IndexOfSelection=2
|
||||||
|
bench_array_test.go:111: IndexOfSelection=2
|
||||||
|
bench_array_test.go:111: IndexOfSelection=2
|
||||||
|
BenchmarkMetalReviewExample 5000 336823 ns/op
|
||||||
|
--- BENCH: BenchmarkMetalReviewExample
|
||||||
|
bench_example_test.go:40: Review 0: Midnight - Complete and Total Hell (8.5).
|
||||||
|
Review 1: Over Your Threshold - Facticity (6.0).
|
||||||
|
Review 2: Nuclear Death Terror - Chaos Reigns (7.5).
|
||||||
|
Review 3: Evoken - Atra Mors (9.5).
|
||||||
|
|
||||||
|
bench_example_test.go:41: MetalReviewExample=10
|
||||||
|
bench_example_test.go:40: Review 0: Midnight - Complete and Total Hell (8.5).
|
||||||
|
Review 1: Over Your Threshold - Facticity (6.0).
|
||||||
|
Review 2: Nuclear Death Terror - Chaos Reigns (7.5).
|
||||||
|
Review 3: Evoken - Atra Mors (9.5).
|
||||||
|
... [output truncated]
|
||||||
|
BenchmarkAdd 50000 54709 ns/op
|
||||||
|
--- BENCH: BenchmarkAdd
|
||||||
|
bench_expand_test.go:20: Add=43
|
||||||
|
bench_expand_test.go:20: Add=43
|
||||||
|
bench_expand_test.go:20: Add=43
|
||||||
|
bench_expand_test.go:20: Add=43
|
||||||
|
BenchmarkAddSelection 10000000 209 ns/op
|
||||||
|
--- BENCH: BenchmarkAddSelection
|
||||||
|
bench_expand_test.go:37: AddSelection=43
|
||||||
|
bench_expand_test.go:37: AddSelection=43
|
||||||
|
bench_expand_test.go:37: AddSelection=43
|
||||||
|
bench_expand_test.go:37: AddSelection=43
|
||||||
|
bench_expand_test.go:37: AddSelection=43
|
||||||
|
BenchmarkAddNodes 10000000 202 ns/op
|
||||||
|
--- BENCH: BenchmarkAddNodes
|
||||||
|
bench_expand_test.go:55: AddNodes=43
|
||||||
|
bench_expand_test.go:55: AddNodes=43
|
||||||
|
bench_expand_test.go:55: AddNodes=43
|
||||||
|
bench_expand_test.go:55: AddNodes=43
|
||||||
|
bench_expand_test.go:55: AddNodes=43
|
||||||
|
BenchmarkAndSelf 1000000 2634 ns/op
|
||||||
|
--- BENCH: BenchmarkAndSelf
|
||||||
|
bench_expand_test.go:71: AndSelf=44
|
||||||
|
bench_expand_test.go:71: AndSelf=44
|
||||||
|
bench_expand_test.go:71: AndSelf=44
|
||||||
|
bench_expand_test.go:71: AndSelf=44
|
||||||
|
BenchmarkFilter 50000 31049 ns/op
|
||||||
|
--- BENCH: BenchmarkFilter
|
||||||
|
bench_filter_test.go:20: Filter=13
|
||||||
|
bench_filter_test.go:20: Filter=13
|
||||||
|
bench_filter_test.go:20: Filter=13
|
||||||
|
bench_filter_test.go:20: Filter=13
|
||||||
|
BenchmarkNot 50000 35167 ns/op
|
||||||
|
--- BENCH: BenchmarkNot
|
||||||
|
bench_filter_test.go:36: Not=371
|
||||||
|
bench_filter_test.go:36: Not=371
|
||||||
|
bench_filter_test.go:36: Not=371
|
||||||
|
bench_filter_test.go:36: Not=371
|
||||||
|
BenchmarkFilterFunction 50000 68974 ns/op
|
||||||
|
--- BENCH: BenchmarkFilterFunction
|
||||||
|
bench_filter_test.go:55: FilterFunction=112
|
||||||
|
bench_filter_test.go:55: FilterFunction=112
|
||||||
|
bench_filter_test.go:55: FilterFunction=112
|
||||||
|
bench_filter_test.go:55: FilterFunction=112
|
||||||
|
BenchmarkNotFunction 50000 74760 ns/op
|
||||||
|
--- BENCH: BenchmarkNotFunction
|
||||||
|
bench_filter_test.go:74: NotFunction=261
|
||||||
|
bench_filter_test.go:74: NotFunction=261
|
||||||
|
bench_filter_test.go:74: NotFunction=261
|
||||||
|
bench_filter_test.go:74: NotFunction=261
|
||||||
|
BenchmarkFilterNodes 50000 68670 ns/op
|
||||||
|
--- BENCH: BenchmarkFilterNodes
|
||||||
|
bench_filter_test.go:92: FilterNodes=2
|
||||||
|
bench_filter_test.go:92: FilterNodes=2
|
||||||
|
bench_filter_test.go:92: FilterNodes=2
|
||||||
|
bench_filter_test.go:92: FilterNodes=2
|
||||||
|
BenchmarkNotNodes 20000 81357 ns/op
|
||||||
|
--- BENCH: BenchmarkNotNodes
|
||||||
|
bench_filter_test.go:110: NotNodes=360
|
||||||
|
bench_filter_test.go:110: NotNodes=360
|
||||||
|
bench_filter_test.go:110: NotNodes=360
|
||||||
|
bench_filter_test.go:110: NotNodes=360
|
||||||
|
BenchmarkFilterSelection 50000 68388 ns/op
|
||||||
|
--- BENCH: BenchmarkFilterSelection
|
||||||
|
bench_filter_test.go:127: FilterSelection=2
|
||||||
|
bench_filter_test.go:127: FilterSelection=2
|
||||||
|
bench_filter_test.go:127: FilterSelection=2
|
||||||
|
bench_filter_test.go:127: FilterSelection=2
|
||||||
|
BenchmarkNotSelection 20000 82108 ns/op
|
||||||
|
--- BENCH: BenchmarkNotSelection
|
||||||
|
bench_filter_test.go:144: NotSelection=360
|
||||||
|
bench_filter_test.go:144: NotSelection=360
|
||||||
|
bench_filter_test.go:144: NotSelection=360
|
||||||
|
bench_filter_test.go:144: NotSelection=360
|
||||||
|
BenchmarkHas 5000 582934 ns/op
|
||||||
|
--- BENCH: BenchmarkHas
|
||||||
|
bench_filter_test.go:160: Has=13
|
||||||
|
bench_filter_test.go:160: Has=13
|
||||||
|
bench_filter_test.go:160: Has=13
|
||||||
|
BenchmarkHasNodes 10000 241602 ns/op
|
||||||
|
--- BENCH: BenchmarkHasNodes
|
||||||
|
bench_filter_test.go:178: HasNodes=15
|
||||||
|
bench_filter_test.go:178: HasNodes=15
|
||||||
|
bench_filter_test.go:178: HasNodes=15
|
||||||
|
BenchmarkHasSelection 10000 243612 ns/op
|
||||||
|
--- BENCH: BenchmarkHasSelection
|
||||||
|
bench_filter_test.go:195: HasSelection=15
|
||||||
|
bench_filter_test.go:195: HasSelection=15
|
||||||
|
bench_filter_test.go:195: HasSelection=15
|
||||||
|
BenchmarkEnd 500000000 4.14 ns/op
|
||||||
|
--- BENCH: BenchmarkEnd
|
||||||
|
bench_filter_test.go:211: End=373
|
||||||
|
bench_filter_test.go:211: End=373
|
||||||
|
bench_filter_test.go:211: End=373
|
||||||
|
bench_filter_test.go:211: End=373
|
||||||
|
bench_filter_test.go:211: End=373
|
||||||
|
bench_filter_test.go:211: End=373
|
||||||
|
BenchmarkEach 200000 9848 ns/op
|
||||||
|
--- BENCH: BenchmarkEach
|
||||||
|
bench_iteration_test.go:22: Each=59
|
||||||
|
bench_iteration_test.go:22: Each=59
|
||||||
|
bench_iteration_test.go:22: Each=59
|
||||||
|
bench_iteration_test.go:22: Each=59
|
||||||
|
BenchmarkMap 100000 17569 ns/op
|
||||||
|
--- BENCH: BenchmarkMap
|
||||||
|
bench_iteration_test.go:41: Map=59
|
||||||
|
bench_iteration_test.go:41: Map=59
|
||||||
|
bench_iteration_test.go:41: Map=59
|
||||||
|
bench_iteration_test.go:41: Map=59
|
||||||
|
BenchmarkAttr 50000000 37.6 ns/op
|
||||||
|
--- BENCH: BenchmarkAttr
|
||||||
|
bench_property_test.go:16: Attr=firstHeading
|
||||||
|
bench_property_test.go:16: Attr=firstHeading
|
||||||
|
bench_property_test.go:16: Attr=firstHeading
|
||||||
|
bench_property_test.go:16: Attr=firstHeading
|
||||||
|
bench_property_test.go:16: Attr=firstHeading
|
||||||
|
BenchmarkText 100000 19345 ns/op
|
||||||
|
BenchmarkLength 2000000000 0.80 ns/op
|
||||||
|
--- BENCH: BenchmarkLength
|
||||||
|
bench_property_test.go:37: Length=14
|
||||||
|
bench_property_test.go:37: Length=14
|
||||||
|
bench_property_test.go:37: Length=14
|
||||||
|
bench_property_test.go:37: Length=14
|
||||||
|
bench_property_test.go:37: Length=14
|
||||||
|
bench_property_test.go:37: Length=14
|
||||||
|
BenchmarkHtml 5000000 688 ns/op
|
||||||
|
BenchmarkIs 50000 35061 ns/op
|
||||||
|
--- BENCH: BenchmarkIs
|
||||||
|
bench_query_test.go:16: Is=true
|
||||||
|
bench_query_test.go:16: Is=true
|
||||||
|
bench_query_test.go:16: Is=true
|
||||||
|
bench_query_test.go:16: Is=true
|
||||||
|
BenchmarkIsPositional 50000 32789 ns/op
|
||||||
|
--- BENCH: BenchmarkIsPositional
|
||||||
|
bench_query_test.go:28: IsPositional=true
|
||||||
|
bench_query_test.go:28: IsPositional=true
|
||||||
|
bench_query_test.go:28: IsPositional=true
|
||||||
|
bench_query_test.go:28: IsPositional=true
|
||||||
|
BenchmarkIsFunction 1000000 2816 ns/op
|
||||||
|
--- BENCH: BenchmarkIsFunction
|
||||||
|
bench_query_test.go:43: IsFunction=true
|
||||||
|
bench_query_test.go:43: IsFunction=true
|
||||||
|
bench_query_test.go:43: IsFunction=true
|
||||||
|
bench_query_test.go:43: IsFunction=true
|
||||||
|
BenchmarkIsSelection 50000 68272 ns/op
|
||||||
|
--- BENCH: BenchmarkIsSelection
|
||||||
|
bench_query_test.go:56: IsSelection=true
|
||||||
|
bench_query_test.go:56: IsSelection=true
|
||||||
|
bench_query_test.go:56: IsSelection=true
|
||||||
|
bench_query_test.go:56: IsSelection=true
|
||||||
|
BenchmarkIsNodes 50000 68107 ns/op
|
||||||
|
--- BENCH: BenchmarkIsNodes
|
||||||
|
bench_query_test.go:70: IsNodes=true
|
||||||
|
bench_query_test.go:70: IsNodes=true
|
||||||
|
bench_query_test.go:70: IsNodes=true
|
||||||
|
bench_query_test.go:70: IsNodes=true
|
||||||
|
BenchmarkHasClass 5000 709386 ns/op
|
||||||
|
--- BENCH: BenchmarkHasClass
|
||||||
|
bench_query_test.go:82: HasClass=true
|
||||||
|
bench_query_test.go:82: HasClass=true
|
||||||
|
bench_query_test.go:82: HasClass=true
|
||||||
|
BenchmarkContains 100000000 12.4 ns/op
|
||||||
|
--- BENCH: BenchmarkContains
|
||||||
|
bench_query_test.go:96: Contains=true
|
||||||
|
bench_query_test.go:96: Contains=true
|
||||||
|
bench_query_test.go:96: Contains=true
|
||||||
|
bench_query_test.go:96: Contains=true
|
||||||
|
bench_query_test.go:96: Contains=true
|
||||||
|
BenchmarkFind 50000 56342 ns/op
|
||||||
|
--- BENCH: BenchmarkFind
|
||||||
|
bench_traversal_test.go:18: Find=41
|
||||||
|
bench_traversal_test.go:18: Find=41
|
||||||
|
bench_traversal_test.go:18: Find=41
|
||||||
|
bench_traversal_test.go:18: Find=41
|
||||||
|
BenchmarkFindWithinSelection 10000 131878 ns/op
|
||||||
|
--- BENCH: BenchmarkFindWithinSelection
|
||||||
|
bench_traversal_test.go:34: FindWithinSelection=39
|
||||||
|
bench_traversal_test.go:34: FindWithinSelection=39
|
||||||
|
bench_traversal_test.go:34: FindWithinSelection=39
|
||||||
|
BenchmarkFindSelection 5000 374240 ns/op
|
||||||
|
--- BENCH: BenchmarkFindSelection
|
||||||
|
bench_traversal_test.go:51: FindSelection=73
|
||||||
|
bench_traversal_test.go:51: FindSelection=73
|
||||||
|
bench_traversal_test.go:51: FindSelection=73
|
||||||
|
BenchmarkFindNodes 5000 374447 ns/op
|
||||||
|
--- BENCH: BenchmarkFindNodes
|
||||||
|
bench_traversal_test.go:69: FindNodes=73
|
||||||
|
bench_traversal_test.go:69: FindNodes=73
|
||||||
|
bench_traversal_test.go:69: FindNodes=73
|
||||||
|
BenchmarkContents 200000 9721 ns/op
|
||||||
|
--- BENCH: BenchmarkContents
|
||||||
|
bench_traversal_test.go:85: Contents=16
|
||||||
|
bench_traversal_test.go:85: Contents=16
|
||||||
|
bench_traversal_test.go:85: Contents=16
|
||||||
|
bench_traversal_test.go:85: Contents=16
|
||||||
|
BenchmarkContentsFiltered 200000 12909 ns/op
|
||||||
|
--- BENCH: BenchmarkContentsFiltered
|
||||||
|
bench_traversal_test.go:101: ContentsFiltered=1
|
||||||
|
bench_traversal_test.go:101: ContentsFiltered=1
|
||||||
|
bench_traversal_test.go:101: ContentsFiltered=1
|
||||||
|
bench_traversal_test.go:101: ContentsFiltered=1
|
||||||
|
BenchmarkChildren 1000000 1869 ns/op
|
||||||
|
--- BENCH: BenchmarkChildren
|
||||||
|
bench_traversal_test.go:117: Children=2
|
||||||
|
bench_traversal_test.go:117: Children=2
|
||||||
|
bench_traversal_test.go:117: Children=2
|
||||||
|
bench_traversal_test.go:117: Children=2
|
||||||
|
BenchmarkChildrenFiltered 500000 5941 ns/op
|
||||||
|
--- BENCH: BenchmarkChildrenFiltered
|
||||||
|
bench_traversal_test.go:133: ChildrenFiltered=2
|
||||||
|
bench_traversal_test.go:133: ChildrenFiltered=2
|
||||||
|
bench_traversal_test.go:133: ChildrenFiltered=2
|
||||||
|
bench_traversal_test.go:133: ChildrenFiltered=2
|
||||||
|
BenchmarkParent 50000 46223 ns/op
|
||||||
|
--- BENCH: BenchmarkParent
|
||||||
|
bench_traversal_test.go:149: Parent=55
|
||||||
|
bench_traversal_test.go:149: Parent=55
|
||||||
|
bench_traversal_test.go:149: Parent=55
|
||||||
|
bench_traversal_test.go:149: Parent=55
|
||||||
|
BenchmarkParentFiltered 50000 51452 ns/op
|
||||||
|
--- BENCH: BenchmarkParentFiltered
|
||||||
|
bench_traversal_test.go:165: ParentFiltered=4
|
||||||
|
bench_traversal_test.go:165: ParentFiltered=4
|
||||||
|
bench_traversal_test.go:165: ParentFiltered=4
|
||||||
|
bench_traversal_test.go:165: ParentFiltered=4
|
||||||
|
BenchmarkParents 20000 93967 ns/op
|
||||||
|
--- BENCH: BenchmarkParents
|
||||||
|
bench_traversal_test.go:181: Parents=73
|
||||||
|
bench_traversal_test.go:181: Parents=73
|
||||||
|
bench_traversal_test.go:181: Parents=73
|
||||||
|
bench_traversal_test.go:181: Parents=73
|
||||||
|
BenchmarkParentsFiltered 20000 97617 ns/op
|
||||||
|
--- BENCH: BenchmarkParentsFiltered
|
||||||
|
bench_traversal_test.go:197: ParentsFiltered=18
|
||||||
|
bench_traversal_test.go:197: ParentsFiltered=18
|
||||||
|
bench_traversal_test.go:197: ParentsFiltered=18
|
||||||
|
bench_traversal_test.go:197: ParentsFiltered=18
|
||||||
|
BenchmarkParentsUntil 10000 138898 ns/op
|
||||||
|
--- BENCH: BenchmarkParentsUntil
|
||||||
|
bench_traversal_test.go:213: ParentsUntil=52
|
||||||
|
bench_traversal_test.go:213: ParentsUntil=52
|
||||||
|
bench_traversal_test.go:213: ParentsUntil=52
|
||||||
|
BenchmarkParentsUntilSelection 10000 247817 ns/op
|
||||||
|
--- BENCH: BenchmarkParentsUntilSelection
|
||||||
|
bench_traversal_test.go:230: ParentsUntilSelection=70
|
||||||
|
bench_traversal_test.go:230: ParentsUntilSelection=70
|
||||||
|
bench_traversal_test.go:230: ParentsUntilSelection=70
|
||||||
|
BenchmarkParentsUntilNodes 10000 246055 ns/op
|
||||||
|
--- BENCH: BenchmarkParentsUntilNodes
|
||||||
|
bench_traversal_test.go:248: ParentsUntilNodes=70
|
||||||
|
bench_traversal_test.go:248: ParentsUntilNodes=70
|
||||||
|
bench_traversal_test.go:248: ParentsUntilNodes=70
|
||||||
|
BenchmarkParentsFilteredUntil 50000 33201 ns/op
|
||||||
|
--- BENCH: BenchmarkParentsFilteredUntil
|
||||||
|
bench_traversal_test.go:264: ParentsFilteredUntil=2
|
||||||
|
bench_traversal_test.go:264: ParentsFilteredUntil=2
|
||||||
|
bench_traversal_test.go:264: ParentsFilteredUntil=2
|
||||||
|
bench_traversal_test.go:264: ParentsFilteredUntil=2
|
||||||
|
BenchmarkParentsFilteredUntilSelection 50000 31486 ns/op
|
||||||
|
--- BENCH: BenchmarkParentsFilteredUntilSelection
|
||||||
|
bench_traversal_test.go:281: ParentsFilteredUntilSelection=2
|
||||||
|
bench_traversal_test.go:281: ParentsFilteredUntilSelection=2
|
||||||
|
bench_traversal_test.go:281: ParentsFilteredUntilSelection=2
|
||||||
|
bench_traversal_test.go:281: ParentsFilteredUntilSelection=2
|
||||||
|
BenchmarkParentsFilteredUntilNodes 50000 31754 ns/op
|
||||||
|
--- BENCH: BenchmarkParentsFilteredUntilNodes
|
||||||
|
bench_traversal_test.go:299: ParentsFilteredUntilNodes=2
|
||||||
|
bench_traversal_test.go:299: ParentsFilteredUntilNodes=2
|
||||||
|
bench_traversal_test.go:299: ParentsFilteredUntilNodes=2
|
||||||
|
bench_traversal_test.go:299: ParentsFilteredUntilNodes=2
|
||||||
|
BenchmarkSiblings 20000 94749 ns/op
|
||||||
|
--- BENCH: BenchmarkSiblings
|
||||||
|
bench_traversal_test.go:315: Siblings=293
|
||||||
|
bench_traversal_test.go:315: Siblings=293
|
||||||
|
bench_traversal_test.go:315: Siblings=293
|
||||||
|
bench_traversal_test.go:315: Siblings=293
|
||||||
|
BenchmarkSiblingsFiltered 10000 103926 ns/op
|
||||||
|
--- BENCH: BenchmarkSiblingsFiltered
|
||||||
|
bench_traversal_test.go:331: SiblingsFiltered=46
|
||||||
|
bench_traversal_test.go:331: SiblingsFiltered=46
|
||||||
|
bench_traversal_test.go:331: SiblingsFiltered=46
|
||||||
|
BenchmarkNext 50000 33782 ns/op
|
||||||
|
--- BENCH: BenchmarkNext
|
||||||
|
bench_traversal_test.go:347: Next=49
|
||||||
|
bench_traversal_test.go:347: Next=49
|
||||||
|
bench_traversal_test.go:347: Next=49
|
||||||
|
bench_traversal_test.go:347: Next=49
|
||||||
|
BenchmarkNextFiltered 50000 37108 ns/op
|
||||||
|
--- BENCH: BenchmarkNextFiltered
|
||||||
|
bench_traversal_test.go:363: NextFiltered=6
|
||||||
|
bench_traversal_test.go:363: NextFiltered=6
|
||||||
|
bench_traversal_test.go:363: NextFiltered=6
|
||||||
|
bench_traversal_test.go:363: NextFiltered=6
|
||||||
|
BenchmarkNextAll 50000 64769 ns/op
|
||||||
|
--- BENCH: BenchmarkNextAll
|
||||||
|
bench_traversal_test.go:379: NextAll=234
|
||||||
|
bench_traversal_test.go:379: NextAll=234
|
||||||
|
bench_traversal_test.go:379: NextAll=234
|
||||||
|
bench_traversal_test.go:379: NextAll=234
|
||||||
|
BenchmarkNextAllFiltered 50000 71050 ns/op
|
||||||
|
--- BENCH: BenchmarkNextAllFiltered
|
||||||
|
bench_traversal_test.go:395: NextAllFiltered=33
|
||||||
|
bench_traversal_test.go:395: NextAllFiltered=33
|
||||||
|
bench_traversal_test.go:395: NextAllFiltered=33
|
||||||
|
bench_traversal_test.go:395: NextAllFiltered=33
|
||||||
|
BenchmarkPrev 50000 33908 ns/op
|
||||||
|
--- BENCH: BenchmarkPrev
|
||||||
|
bench_traversal_test.go:411: Prev=49
|
||||||
|
bench_traversal_test.go:411: Prev=49
|
||||||
|
bench_traversal_test.go:411: Prev=49
|
||||||
|
bench_traversal_test.go:411: Prev=49
|
||||||
|
BenchmarkPrevFiltered 50000 37353 ns/op
|
||||||
|
--- BENCH: BenchmarkPrevFiltered
|
||||||
|
bench_traversal_test.go:429: PrevFiltered=7
|
||||||
|
bench_traversal_test.go:429: PrevFiltered=7
|
||||||
|
bench_traversal_test.go:429: PrevFiltered=7
|
||||||
|
bench_traversal_test.go:429: PrevFiltered=7
|
||||||
|
BenchmarkPrevAll 50000 31056 ns/op
|
||||||
|
--- BENCH: BenchmarkPrevAll
|
||||||
|
bench_traversal_test.go:445: PrevAll=78
|
||||||
|
bench_traversal_test.go:445: PrevAll=78
|
||||||
|
bench_traversal_test.go:445: PrevAll=78
|
||||||
|
bench_traversal_test.go:445: PrevAll=78
|
||||||
|
BenchmarkPrevAllFiltered 50000 34286 ns/op
|
||||||
|
--- BENCH: BenchmarkPrevAllFiltered
|
||||||
|
bench_traversal_test.go:461: PrevAllFiltered=6
|
||||||
|
bench_traversal_test.go:461: PrevAllFiltered=6
|
||||||
|
bench_traversal_test.go:461: PrevAllFiltered=6
|
||||||
|
bench_traversal_test.go:461: PrevAllFiltered=6
|
||||||
|
BenchmarkNextUntil 10000 202553 ns/op
|
||||||
|
--- BENCH: BenchmarkNextUntil
|
||||||
|
bench_traversal_test.go:477: NextUntil=84
|
||||||
|
bench_traversal_test.go:477: NextUntil=84
|
||||||
|
bench_traversal_test.go:477: NextUntil=84
|
||||||
|
BenchmarkNextUntilSelection 20000 98693 ns/op
|
||||||
|
--- BENCH: BenchmarkNextUntilSelection
|
||||||
|
bench_traversal_test.go:494: NextUntilSelection=42
|
||||||
|
bench_traversal_test.go:494: NextUntilSelection=42
|
||||||
|
bench_traversal_test.go:494: NextUntilSelection=42
|
||||||
|
bench_traversal_test.go:494: NextUntilSelection=42
|
||||||
|
BenchmarkNextUntilNodes 50000 45532 ns/op
|
||||||
|
--- BENCH: BenchmarkNextUntilNodes
|
||||||
|
bench_traversal_test.go:512: NextUntilNodes=12
|
||||||
|
bench_traversal_test.go:512: NextUntilNodes=12
|
||||||
|
bench_traversal_test.go:512: NextUntilNodes=12
|
||||||
|
bench_traversal_test.go:512: NextUntilNodes=12
|
||||||
|
BenchmarkPrevUntil 5000 454378 ns/op
|
||||||
|
--- BENCH: BenchmarkPrevUntil
|
||||||
|
bench_traversal_test.go:528: PrevUntil=238
|
||||||
|
bench_traversal_test.go:528: PrevUntil=238
|
||||||
|
bench_traversal_test.go:528: PrevUntil=238
|
||||||
|
BenchmarkPrevUntilSelection 10000 123594 ns/op
|
||||||
|
--- BENCH: BenchmarkPrevUntilSelection
|
||||||
|
bench_traversal_test.go:545: PrevUntilSelection=49
|
||||||
|
bench_traversal_test.go:545: PrevUntilSelection=49
|
||||||
|
bench_traversal_test.go:545: PrevUntilSelection=49
|
||||||
|
BenchmarkPrevUntilNodes 50000 37509 ns/op
|
||||||
|
--- BENCH: BenchmarkPrevUntilNodes
|
||||||
|
bench_traversal_test.go:563: PrevUntilNodes=11
|
||||||
|
bench_traversal_test.go:563: PrevUntilNodes=11
|
||||||
|
bench_traversal_test.go:563: PrevUntilNodes=11
|
||||||
|
bench_traversal_test.go:563: PrevUntilNodes=11
|
||||||
|
BenchmarkNextFilteredUntil 10000 109317 ns/op
|
||||||
|
--- BENCH: BenchmarkNextFilteredUntil
|
||||||
|
bench_traversal_test.go:579: NextFilteredUntil=22
|
||||||
|
bench_traversal_test.go:579: NextFilteredUntil=22
|
||||||
|
bench_traversal_test.go:579: NextFilteredUntil=22
|
||||||
|
BenchmarkNextFilteredUntilSelection 10000 105959 ns/op
|
||||||
|
--- BENCH: BenchmarkNextFilteredUntilSelection
|
||||||
|
bench_traversal_test.go:596: NextFilteredUntilSelection=22
|
||||||
|
bench_traversal_test.go:596: NextFilteredUntilSelection=22
|
||||||
|
bench_traversal_test.go:596: NextFilteredUntilSelection=22
|
||||||
|
BenchmarkNextFilteredUntilNodes 10000 107132 ns/op
|
||||||
|
--- BENCH: BenchmarkNextFilteredUntilNodes
|
||||||
|
bench_traversal_test.go:614: NextFilteredUntilNodes=22
|
||||||
|
bench_traversal_test.go:614: NextFilteredUntilNodes=22
|
||||||
|
bench_traversal_test.go:614: NextFilteredUntilNodes=22
|
||||||
|
BenchmarkPrevFilteredUntil 10000 114474 ns/op
|
||||||
|
--- BENCH: BenchmarkPrevFilteredUntil
|
||||||
|
bench_traversal_test.go:630: PrevFilteredUntil=20
|
||||||
|
bench_traversal_test.go:630: PrevFilteredUntil=20
|
||||||
|
bench_traversal_test.go:630: PrevFilteredUntil=20
|
||||||
|
BenchmarkPrevFilteredUntilSelection 10000 107592 ns/op
|
||||||
|
--- BENCH: BenchmarkPrevFilteredUntilSelection
|
||||||
|
bench_traversal_test.go:647: PrevFilteredUntilSelection=20
|
||||||
|
bench_traversal_test.go:647: PrevFilteredUntilSelection=20
|
||||||
|
bench_traversal_test.go:647: PrevFilteredUntilSelection=20
|
||||||
|
BenchmarkPrevFilteredUntilNodes 10000 107495 ns/op
|
||||||
|
--- BENCH: BenchmarkPrevFilteredUntilNodes
|
||||||
|
bench_traversal_test.go:665: PrevFilteredUntilNodes=20
|
||||||
|
bench_traversal_test.go:665: PrevFilteredUntilNodes=20
|
||||||
|
bench_traversal_test.go:665: PrevFilteredUntilNodes=20
|
||||||
|
ok github.com/PuerkitoBio/goquery 187.652s
|
405
Godeps/_workspace/src/github.com/PuerkitoBio/goquery/bench/v0.1.1-v0.2.1-go1.1rc1.svg
generated
vendored
Normal file
405
Godeps/_workspace/src/github.com/PuerkitoBio/goquery/bench/v0.1.1-v0.2.1-go1.1rc1.svg
generated
vendored
Normal file
|
@ -0,0 +1,405 @@
|
||||||
|
<?xml version="1.0"?>
|
||||||
|
<!-- Generated by SVGo -->
|
||||||
|
<svg width="1024" height="768"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||||
|
<g style="font-size:20px;font-family:sans-serif">
|
||||||
|
<rect x="0" y="0" width="1024" height="768" style="fill:white"/>
|
||||||
|
<text x="100" y="50" style="font-size:150%"></text>
|
||||||
|
<g style="font-style:italic;font-size:75%">
|
||||||
|
<rect x="612" y="118" width="0" height="20" style="fill-opacity:0.3;fill:red"/>
|
||||||
|
<text x="607" y="133" style="text-anchor:end">+0.10%</text>
|
||||||
|
</g>
|
||||||
|
<text x="100" y="138" style="text-anchor:start">BenchmarkFirst</text>
|
||||||
|
<g style="font-style:italic;font-size:75%">
|
||||||
|
<rect x="612" y="144" width="0" height="20" style="fill-opacity:0.3;fill:green"/>
|
||||||
|
<text x="617" y="159" style="text-anchor:start">-0.10%</text>
|
||||||
|
</g>
|
||||||
|
<text x="100" y="164" style="text-anchor:start">BenchmarkLast</text>
|
||||||
|
<g style="font-style:italic;font-size:75%">
|
||||||
|
<rect x="604" y="170" width="8" height="20" style="fill-opacity:0.3;fill:red"/>
|
||||||
|
<text x="599" y="185" style="text-anchor:end">+2.86%</text>
|
||||||
|
</g>
|
||||||
|
<text x="100" y="190" style="text-anchor:start">BenchmarkEq</text>
|
||||||
|
<g style="font-style:italic;font-size:75%">
|
||||||
|
<rect x="604" y="196" width="8" height="20" style="fill-opacity:0.3;fill:red"/>
|
||||||
|
<text x="599" y="211" style="text-anchor:end">+2.67%</text>
|
||||||
|
</g>
|
||||||
|
<text x="100" y="216" style="text-anchor:start">BenchmarkSlice</text>
|
||||||
|
<g style="font-style:italic;font-size:75%">
|
||||||
|
<rect x="612" y="222" width="32" height="20" style="fill-opacity:0.3;fill:green"/>
|
||||||
|
<text x="649" y="237" style="text-anchor:start">-10.82%</text>
|
||||||
|
</g>
|
||||||
|
<text x="100" y="242" style="text-anchor:start">BenchmarkGet</text>
|
||||||
|
<g style="font-style:italic;font-size:75%">
|
||||||
|
<rect x="612" y="248" width="132" height="20" style="fill-opacity:0.3;fill:green"/>
|
||||||
|
<text x="749" y="263" style="text-anchor:start">-44.06%</text>
|
||||||
|
</g>
|
||||||
|
<text x="100" y="268" style="text-anchor:start">BenchmarkIndex</text>
|
||||||
|
<g style="font-style:italic;font-size:75%">
|
||||||
|
<rect x="612" y="274" width="156" height="20" style="fill-opacity:0.3;fill:green"/>
|
||||||
|
<text x="773" y="289" style="text-anchor:start">-52.26%</text>
|
||||||
|
</g>
|
||||||
|
<text x="100" y="294" style="text-anchor:start">BenchmarkIndexSelector</text>
|
||||||
|
<g style="font-style:italic;font-size:75%">
|
||||||
|
<rect x="612" y="300" width="27" height="20" style="fill-opacity:0.3;fill:green"/>
|
||||||
|
<text x="644" y="315" style="text-anchor:start">-9.32%</text>
|
||||||
|
</g>
|
||||||
|
<text x="100" y="320" style="text-anchor:start">BenchmarkIndexOfNode</text>
|
||||||
|
<g style="font-style:italic;font-size:75%">
|
||||||
|
<rect x="612" y="326" width="7" height="20" style="fill-opacity:0.3;fill:green"/>
|
||||||
|
<text x="624" y="341" style="text-anchor:start">-2.48%</text>
|
||||||
|
</g>
|
||||||
|
<text x="100" y="346" style="text-anchor:start">BenchmarkIndexOfSelection</text>
|
||||||
|
<g style="font-style:italic;font-size:75%">
|
||||||
|
<rect x="612" y="352" width="104" height="20" style="fill-opacity:0.3;fill:green"/>
|
||||||
|
<text x="721" y="367" style="text-anchor:start">-34.96%</text>
|
||||||
|
</g>
|
||||||
|
<text x="100" y="372" style="text-anchor:start">BenchmarkMetalReviewExample</text>
|
||||||
|
<g style="font-style:italic;font-size:75%">
|
||||||
|
<rect x="612" y="378" width="177" height="20" style="fill-opacity:0.3;fill:green"/>
|
||||||
|
<text x="794" y="393" style="text-anchor:start">-59.16%</text>
|
||||||
|
</g>
|
||||||
|
<text x="100" y="398" style="text-anchor:start">BenchmarkAdd</text>
|
||||||
|
<g style="font-style:italic;font-size:75%">
|
||||||
|
<rect x="612" y="404" width="0" height="20" style="fill-opacity:0.3;fill:green"/>
|
||||||
|
<text x="617" y="419" style="text-anchor:start">+0.00%</text>
|
||||||
|
</g>
|
||||||
|
<text x="100" y="424" style="text-anchor:start">BenchmarkAddSelection</text>
|
||||||
|
<g style="font-style:italic;font-size:75%">
|
||||||
|
<rect x="602" y="430" width="10" height="20" style="fill-opacity:0.3;fill:red"/>
|
||||||
|
<text x="597" y="445" style="text-anchor:end">+3.47%</text>
|
||||||
|
</g>
|
||||||
|
<text x="100" y="450" style="text-anchor:start">BenchmarkAddNodes</text>
|
||||||
|
<g style="font-style:italic;font-size:75%">
|
||||||
|
<rect x="612" y="456" width="7" height="20" style="fill-opacity:0.3;fill:green"/>
|
||||||
|
<text x="624" y="471" style="text-anchor:start">-2.51%</text>
|
||||||
|
</g>
|
||||||
|
<text x="100" y="476" style="text-anchor:start">BenchmarkAndSelf</text>
|
||||||
|
<g style="font-style:italic;font-size:75%">
|
||||||
|
<rect x="612" y="482" width="41" height="20" style="fill-opacity:0.3;fill:green"/>
|
||||||
|
<text x="658" y="497" style="text-anchor:start">-13.96%</text>
|
||||||
|
</g>
|
||||||
|
<text x="100" y="502" style="text-anchor:start">BenchmarkFilter</text>
|
||||||
|
<g style="font-style:italic;font-size:75%">
|
||||||
|
<rect x="612" y="508" width="43" height="20" style="fill-opacity:0.3;fill:green"/>
|
||||||
|
<text x="660" y="523" style="text-anchor:start">-14.53%</text>
|
||||||
|
</g>
|
||||||
|
<text x="100" y="528" style="text-anchor:start">BenchmarkNot</text>
|
||||||
|
<g style="font-style:italic;font-size:75%">
|
||||||
|
<rect x="612" y="534" width="11" height="20" style="fill-opacity:0.3;fill:green"/>
|
||||||
|
<text x="628" y="549" style="text-anchor:start">-3.81%</text>
|
||||||
|
</g>
|
||||||
|
<text x="100" y="554" style="text-anchor:start">BenchmarkFilterFunction</text>
|
||||||
|
<g style="font-style:italic;font-size:75%">
|
||||||
|
<rect x="612" y="560" width="8" height="20" style="fill-opacity:0.3;fill:green"/>
|
||||||
|
<text x="625" y="575" style="text-anchor:start">-2.83%</text>
|
||||||
|
</g>
|
||||||
|
<text x="100" y="580" style="text-anchor:start">BenchmarkNotFunction</text>
|
||||||
|
<g style="font-style:italic;font-size:75%">
|
||||||
|
<rect x="612" y="586" width="13" height="20" style="fill-opacity:0.3;fill:green"/>
|
||||||
|
<text x="630" y="601" style="text-anchor:start">-4.63%</text>
|
||||||
|
</g>
|
||||||
|
<text x="100" y="606" style="text-anchor:start">BenchmarkFilterNodes</text>
|
||||||
|
<g style="font-style:italic;font-size:75%">
|
||||||
|
<rect x="612" y="612" width="6" height="20" style="fill-opacity:0.3;fill:green"/>
|
||||||
|
<text x="623" y="627" style="text-anchor:start">-2.32%</text>
|
||||||
|
</g>
|
||||||
|
<text x="100" y="632" style="text-anchor:start">BenchmarkNotNodes</text>
|
||||||
|
<g style="font-style:italic;font-size:75%">
|
||||||
|
<rect x="612" y="638" width="12" height="20" style="fill-opacity:0.3;fill:green"/>
|
||||||
|
<text x="629" y="653" style="text-anchor:start">-4.23%</text>
|
||||||
|
</g>
|
||||||
|
<text x="100" y="658" style="text-anchor:start">BenchmarkFilterSelection</text>
|
||||||
|
<g style="font-style:italic;font-size:75%">
|
||||||
|
<rect x="612" y="664" width="9" height="20" style="fill-opacity:0.3;fill:green"/>
|
||||||
|
<text x="626" y="679" style="text-anchor:start">-3.31%</text>
|
||||||
|
</g>
|
||||||
|
<text x="100" y="684" style="text-anchor:start">BenchmarkNotSelection</text>
|
||||||
|
<g style="font-style:italic;font-size:75%">
|
||||||
|
<rect x="612" y="690" width="101" height="20" style="fill-opacity:0.3;fill:green"/>
|
||||||
|
<text x="718" y="705" style="text-anchor:start">-33.69%</text>
|
||||||
|
</g>
|
||||||
|
<text x="100" y="710" style="text-anchor:start">BenchmarkHas</text>
|
||||||
|
<g style="font-style:italic;font-size:75%">
|
||||||
|
<rect x="612" y="716" width="13" height="20" style="fill-opacity:0.3;fill:green"/>
|
||||||
|
<text x="630" y="731" style="text-anchor:start">-4.53%</text>
|
||||||
|
</g>
|
||||||
|
<text x="100" y="736" style="text-anchor:start">BenchmarkHasNodes</text>
|
||||||
|
<g style="font-style:italic;font-size:75%">
|
||||||
|
<rect x="612" y="742" width="15" height="20" style="fill-opacity:0.3;fill:green"/>
|
||||||
|
<text x="632" y="757" style="text-anchor:start">-5.30%</text>
|
||||||
|
</g>
|
||||||
|
<text x="100" y="762" style="text-anchor:start">BenchmarkHasSelection</text>
|
||||||
|
<g style="font-style:italic;font-size:75%">
|
||||||
|
<rect x="578" y="768" width="34" height="20" style="fill-opacity:0.3;fill:red"/>
|
||||||
|
<text x="573" y="783" style="text-anchor:end">+11.35%</text>
|
||||||
|
</g>
|
||||||
|
<text x="100" y="788" style="text-anchor:start">BenchmarkEnd</text>
|
||||||
|
<g style="font-style:italic;font-size:75%">
|
||||||
|
<rect x="612" y="794" width="9" height="20" style="fill-opacity:0.3;fill:green"/>
|
||||||
|
<text x="626" y="809" style="text-anchor:start">-3.33%</text>
|
||||||
|
</g>
|
||||||
|
<text x="100" y="814" style="text-anchor:start">BenchmarkEach</text>
|
||||||
|
<g style="font-style:italic;font-size:75%">
|
||||||
|
<rect x="612" y="820" width="27" height="20" style="fill-opacity:0.3;fill:green"/>
|
||||||
|
<text x="644" y="835" style="text-anchor:start">-9.16%</text>
|
||||||
|
</g>
|
||||||
|
<text x="100" y="840" style="text-anchor:start">BenchmarkMap</text>
|
||||||
|
<g style="font-style:italic;font-size:75%">
|
||||||
|
<rect x="612" y="846" width="57" height="20" style="fill-opacity:0.3;fill:green"/>
|
||||||
|
<text x="674" y="861" style="text-anchor:start">-19.15%</text>
|
||||||
|
</g>
|
||||||
|
<text x="100" y="866" style="text-anchor:start">BenchmarkAttr</text>
|
||||||
|
<g style="font-style:italic;font-size:75%">
|
||||||
|
<rect x="612" y="872" width="9" height="20" style="fill-opacity:0.3;fill:green"/>
|
||||||
|
<text x="626" y="887" style="text-anchor:start">-3.24%</text>
|
||||||
|
</g>
|
||||||
|
<text x="100" y="892" style="text-anchor:start">BenchmarkText</text>
|
||||||
|
<g style="font-style:italic;font-size:75%">
|
||||||
|
<rect x="612" y="898" width="183" height="20" style="fill-opacity:0.3;fill:green"/>
|
||||||
|
<text x="800" y="913" style="text-anchor:start">-61.25%</text>
|
||||||
|
</g>
|
||||||
|
<text x="100" y="918" style="text-anchor:start">BenchmarkLength</text>
|
||||||
|
<g style="font-style:italic;font-size:75%">
|
||||||
|
<rect x="612" y="924" width="35" height="20" style="fill-opacity:0.3;fill:green"/>
|
||||||
|
<text x="652" y="939" style="text-anchor:start">-11.92%</text>
|
||||||
|
</g>
|
||||||
|
<text x="100" y="944" style="text-anchor:start">BenchmarkHtml</text>
|
||||||
|
<g style="font-style:italic;font-size:75%">
|
||||||
|
<rect x="612" y="950" width="49" height="20" style="fill-opacity:0.3;fill:green"/>
|
||||||
|
<text x="666" y="965" style="text-anchor:start">-16.46%</text>
|
||||||
|
</g>
|
||||||
|
<text x="100" y="970" style="text-anchor:start">BenchmarkIs</text>
|
||||||
|
<g style="font-style:italic;font-size:75%">
|
||||||
|
<rect x="612" y="976" width="81" height="20" style="fill-opacity:0.3;fill:green"/>
|
||||||
|
<text x="698" y="991" style="text-anchor:start">-27.31%</text>
|
||||||
|
</g>
|
||||||
|
<text x="100" y="996" style="text-anchor:start">BenchmarkIsPositional</text>
|
||||||
|
<g style="font-style:italic;font-size:75%">
|
||||||
|
<rect x="612" y="1002" width="40" height="20" style="fill-opacity:0.3;fill:green"/>
|
||||||
|
<text x="657" y="1017" style="text-anchor:start">-13.49%</text>
|
||||||
|
</g>
|
||||||
|
<text x="100" y="1022" style="text-anchor:start">BenchmarkIsFunction</text>
|
||||||
|
<g style="font-style:italic;font-size:75%">
|
||||||
|
<rect x="612" y="1028" width="5" height="20" style="fill-opacity:0.3;fill:green"/>
|
||||||
|
<text x="622" y="1043" style="text-anchor:start">-1.71%</text>
|
||||||
|
</g>
|
||||||
|
<text x="100" y="1048" style="text-anchor:start">BenchmarkIsSelection</text>
|
||||||
|
<g style="font-style:italic;font-size:75%">
|
||||||
|
<rect x="612" y="1054" width="9" height="20" style="fill-opacity:0.3;fill:green"/>
|
||||||
|
<text x="626" y="1069" style="text-anchor:start">-3.03%</text>
|
||||||
|
</g>
|
||||||
|
<text x="100" y="1074" style="text-anchor:start">BenchmarkIsNodes</text>
|
||||||
|
<g style="font-style:italic;font-size:75%">
|
||||||
|
<rect x="612" y="1080" width="60" height="20" style="fill-opacity:0.3;fill:green"/>
|
||||||
|
<text x="677" y="1095" style="text-anchor:start">-20.30%</text>
|
||||||
|
</g>
|
||||||
|
<text x="100" y="1100" style="text-anchor:start">BenchmarkHasClass</text>
|
||||||
|
<g style="font-style:italic;font-size:75%">
|
||||||
|
<rect x="612" y="1106" width="33" height="20" style="fill-opacity:0.3;fill:green"/>
|
||||||
|
<text x="650" y="1121" style="text-anchor:start">-11.29%</text>
|
||||||
|
</g>
|
||||||
|
<text x="100" y="1126" style="text-anchor:start">BenchmarkContains</text>
|
||||||
|
<g style="font-style:italic;font-size:75%">
|
||||||
|
<rect x="612" y="1132" width="152" height="20" style="fill-opacity:0.3;fill:green"/>
|
||||||
|
<text x="769" y="1147" style="text-anchor:start">-50.88%</text>
|
||||||
|
</g>
|
||||||
|
<text x="100" y="1152" style="text-anchor:start">BenchmarkFind</text>
|
||||||
|
<g style="font-style:italic;font-size:75%">
|
||||||
|
<rect x="612" y="1158" width="135" height="20" style="fill-opacity:0.3;fill:green"/>
|
||||||
|
<text x="752" y="1173" style="text-anchor:start">-45.28%</text>
|
||||||
|
</g>
|
||||||
|
<text x="100" y="1178" style="text-anchor:start">BenchmarkFindWithinSelection</text>
|
||||||
|
<g style="font-style:italic;font-size:75%">
|
||||||
|
<rect x="544" y="1184" width="68" height="20" style="fill-opacity:0.3;fill:red"/>
|
||||||
|
<text x="539" y="1199" style="text-anchor:end">+22.95%</text>
|
||||||
|
</g>
|
||||||
|
<text x="100" y="1204" style="text-anchor:start">BenchmarkFindSelection</text>
|
||||||
|
<g style="font-style:italic;font-size:75%">
|
||||||
|
<rect x="544" y="1210" width="68" height="20" style="fill-opacity:0.3;fill:red"/>
|
||||||
|
<text x="539" y="1225" style="text-anchor:end">+22.68%</text>
|
||||||
|
</g>
|
||||||
|
<text x="100" y="1230" style="text-anchor:start">BenchmarkFindNodes</text>
|
||||||
|
<g style="font-style:italic;font-size:75%">
|
||||||
|
<rect x="612" y="1236" width="195" height="20" style="fill-opacity:0.3;fill:green"/>
|
||||||
|
<text x="812" y="1251" style="text-anchor:start">-65.08%</text>
|
||||||
|
</g>
|
||||||
|
<text x="100" y="1256" style="text-anchor:start">BenchmarkContents</text>
|
||||||
|
<g style="font-style:italic;font-size:75%">
|
||||||
|
<rect x="612" y="1262" width="179" height="20" style="fill-opacity:0.3;fill:green"/>
|
||||||
|
<text x="796" y="1277" style="text-anchor:start">-59.77%</text>
|
||||||
|
</g>
|
||||||
|
<text x="100" y="1282" style="text-anchor:start">BenchmarkContentsFiltered</text>
|
||||||
|
<g style="font-style:italic;font-size:75%">
|
||||||
|
<rect x="612" y="1288" width="192" height="20" style="fill-opacity:0.3;fill:green"/>
|
||||||
|
<text x="809" y="1303" style="text-anchor:start">-64.31%</text>
|
||||||
|
</g>
|
||||||
|
<text x="100" y="1308" style="text-anchor:start">BenchmarkChildren</text>
|
||||||
|
<g style="font-style:italic;font-size:75%">
|
||||||
|
<rect x="612" y="1314" width="118" height="20" style="fill-opacity:0.3;fill:green"/>
|
||||||
|
<text x="735" y="1329" style="text-anchor:start">-39.56%</text>
|
||||||
|
</g>
|
||||||
|
<text x="100" y="1334" style="text-anchor:start">BenchmarkChildrenFiltered</text>
|
||||||
|
<g style="font-style:italic;font-size:75%">
|
||||||
|
<rect x="612" y="1340" width="19" height="20" style="fill-opacity:0.3;fill:green"/>
|
||||||
|
<text x="636" y="1355" style="text-anchor:start">-6.61%</text>
|
||||||
|
</g>
|
||||||
|
<text x="100" y="1360" style="text-anchor:start">BenchmarkParent</text>
|
||||||
|
<g style="font-style:italic;font-size:75%">
|
||||||
|
<rect x="612" y="1366" width="32" height="20" style="fill-opacity:0.3;fill:green"/>
|
||||||
|
<text x="649" y="1381" style="text-anchor:start">-10.92%</text>
|
||||||
|
</g>
|
||||||
|
<text x="100" y="1386" style="text-anchor:start">BenchmarkParentFiltered</text>
|
||||||
|
<g style="font-style:italic;font-size:75%">
|
||||||
|
<rect x="612" y="1392" width="5" height="20" style="fill-opacity:0.3;fill:green"/>
|
||||||
|
<text x="622" y="1407" style="text-anchor:start">-1.72%</text>
|
||||||
|
</g>
|
||||||
|
<text x="100" y="1412" style="text-anchor:start">BenchmarkParents</text>
|
||||||
|
<g style="font-style:italic;font-size:75%">
|
||||||
|
<rect x="612" y="1418" width="7" height="20" style="fill-opacity:0.3;fill:green"/>
|
||||||
|
<text x="624" y="1433" style="text-anchor:start">-2.37%</text>
|
||||||
|
</g>
|
||||||
|
<text x="100" y="1438" style="text-anchor:start">BenchmarkParentsFiltered</text>
|
||||||
|
<g style="font-style:italic;font-size:75%">
|
||||||
|
<rect x="612" y="1444" width="142" height="20" style="fill-opacity:0.3;fill:green"/>
|
||||||
|
<text x="759" y="1459" style="text-anchor:start">-47.60%</text>
|
||||||
|
</g>
|
||||||
|
<text x="100" y="1464" style="text-anchor:start">BenchmarkParentsUntil</text>
|
||||||
|
<g style="font-style:italic;font-size:75%">
|
||||||
|
<rect x="612" y="1470" width="109" height="20" style="fill-opacity:0.3;fill:green"/>
|
||||||
|
<text x="726" y="1485" style="text-anchor:start">-36.39%</text>
|
||||||
|
</g>
|
||||||
|
<text x="100" y="1490" style="text-anchor:start">BenchmarkParentsUntilSelection</text>
|
||||||
|
<g style="font-style:italic;font-size:75%">
|
||||||
|
<rect x="612" y="1496" width="107" height="20" style="fill-opacity:0.3;fill:green"/>
|
||||||
|
<text x="724" y="1511" style="text-anchor:start">-35.99%</text>
|
||||||
|
</g>
|
||||||
|
<text x="100" y="1516" style="text-anchor:start">BenchmarkParentsUntilNodes</text>
|
||||||
|
<g style="font-style:italic;font-size:75%">
|
||||||
|
<rect x="612" y="1522" width="146" height="20" style="fill-opacity:0.3;fill:green"/>
|
||||||
|
<text x="763" y="1537" style="text-anchor:start">-48.84%</text>
|
||||||
|
</g>
|
||||||
|
<text x="100" y="1542" style="text-anchor:start">BenchmarkParentsFilteredUntil</text>
|
||||||
|
<g style="font-style:italic;font-size:75%">
|
||||||
|
<rect x="612" y="1548" width="98" height="20" style="fill-opacity:0.3;fill:green"/>
|
||||||
|
<text x="715" y="1563" style="text-anchor:start">-32.75%</text>
|
||||||
|
</g>
|
||||||
|
<text x="100" y="1568" style="text-anchor:start">BenchmarkParentsFilteredUntilSelection</text>
|
||||||
|
<g style="font-style:italic;font-size:75%">
|
||||||
|
<rect x="612" y="1574" width="99" height="20" style="fill-opacity:0.3;fill:green"/>
|
||||||
|
<text x="716" y="1589" style="text-anchor:start">-33.12%</text>
|
||||||
|
</g>
|
||||||
|
<text x="100" y="1594" style="text-anchor:start">BenchmarkParentsFilteredUntilNodes</text>
|
||||||
|
<g style="font-style:italic;font-size:75%">
|
||||||
|
<rect x="612" y="1600" width="89" height="20" style="fill-opacity:0.3;fill:green"/>
|
||||||
|
<text x="706" y="1615" style="text-anchor:start">-29.78%</text>
|
||||||
|
</g>
|
||||||
|
<text x="100" y="1620" style="text-anchor:start">BenchmarkSiblings</text>
|
||||||
|
<g style="font-style:italic;font-size:75%">
|
||||||
|
<rect x="612" y="1626" width="92" height="20" style="fill-opacity:0.3;fill:green"/>
|
||||||
|
<text x="709" y="1641" style="text-anchor:start">-30.89%</text>
|
||||||
|
</g>
|
||||||
|
<text x="100" y="1646" style="text-anchor:start">BenchmarkSiblingsFiltered</text>
|
||||||
|
<g style="font-style:italic;font-size:75%">
|
||||||
|
<rect x="612" y="1652" width="204" height="20" style="fill-opacity:0.3;fill:green"/>
|
||||||
|
<text x="821" y="1667" style="text-anchor:start">-68.19%</text>
|
||||||
|
</g>
|
||||||
|
<text x="100" y="1672" style="text-anchor:start">BenchmarkNext</text>
|
||||||
|
<g style="font-style:italic;font-size:75%">
|
||||||
|
<rect x="612" y="1678" width="199" height="20" style="fill-opacity:0.3;fill:green"/>
|
||||||
|
<text x="816" y="1693" style="text-anchor:start">-66.59%</text>
|
||||||
|
</g>
|
||||||
|
<text x="100" y="1698" style="text-anchor:start">BenchmarkNextFiltered</text>
|
||||||
|
<g style="font-style:italic;font-size:75%">
|
||||||
|
<rect x="612" y="1704" width="93" height="20" style="fill-opacity:0.3;fill:green"/>
|
||||||
|
<text x="710" y="1719" style="text-anchor:start">-31.08%</text>
|
||||||
|
</g>
|
||||||
|
<text x="100" y="1724" style="text-anchor:start">BenchmarkNextAll</text>
|
||||||
|
<g style="font-style:italic;font-size:75%">
|
||||||
|
<rect x="612" y="1730" width="90" height="20" style="fill-opacity:0.3;fill:green"/>
|
||||||
|
<text x="707" y="1745" style="text-anchor:start">-30.03%</text>
|
||||||
|
</g>
|
||||||
|
<text x="100" y="1750" style="text-anchor:start">BenchmarkNextAllFiltered</text>
|
||||||
|
<g style="font-style:italic;font-size:75%">
|
||||||
|
<rect x="612" y="1756" width="204" height="20" style="fill-opacity:0.3;fill:green"/>
|
||||||
|
<text x="821" y="1771" style="text-anchor:start">-68.32%</text>
|
||||||
|
</g>
|
||||||
|
<text x="100" y="1776" style="text-anchor:start">BenchmarkPrev</text>
|
||||||
|
<g style="font-style:italic;font-size:75%">
|
||||||
|
<rect x="612" y="1782" width="199" height="20" style="fill-opacity:0.3;fill:green"/>
|
||||||
|
<text x="816" y="1797" style="text-anchor:start">-66.65%</text>
|
||||||
|
</g>
|
||||||
|
<text x="100" y="1802" style="text-anchor:start">BenchmarkPrevFiltered</text>
|
||||||
|
<g style="font-style:italic;font-size:75%">
|
||||||
|
<rect x="612" y="1808" width="129" height="20" style="fill-opacity:0.3;fill:green"/>
|
||||||
|
<text x="746" y="1823" style="text-anchor:start">-43.33%</text>
|
||||||
|
</g>
|
||||||
|
<text x="100" y="1828" style="text-anchor:start">BenchmarkPrevAll</text>
|
||||||
|
<g style="font-style:italic;font-size:75%">
|
||||||
|
<rect x="612" y="1834" width="129" height="20" style="fill-opacity:0.3;fill:green"/>
|
||||||
|
<text x="746" y="1849" style="text-anchor:start">-43.24%</text>
|
||||||
|
</g>
|
||||||
|
<text x="100" y="1854" style="text-anchor:start">BenchmarkPrevAllFiltered</text>
|
||||||
|
<g style="font-style:italic;font-size:75%">
|
||||||
|
<rect x="612" y="1860" width="162" height="20" style="fill-opacity:0.3;fill:green"/>
|
||||||
|
<text x="779" y="1875" style="text-anchor:start">-54.27%</text>
|
||||||
|
</g>
|
||||||
|
<text x="100" y="1880" style="text-anchor:start">BenchmarkNextUntil</text>
|
||||||
|
<g style="font-style:italic;font-size:75%">
|
||||||
|
<rect x="612" y="1886" width="113" height="20" style="fill-opacity:0.3;fill:green"/>
|
||||||
|
<text x="730" y="1901" style="text-anchor:start">-37.90%</text>
|
||||||
|
</g>
|
||||||
|
<text x="100" y="1906" style="text-anchor:start">BenchmarkNextUntilSelection</text>
|
||||||
|
<g style="font-style:italic;font-size:75%">
|
||||||
|
<rect x="612" y="1912" width="129" height="20" style="fill-opacity:0.3;fill:green"/>
|
||||||
|
<text x="746" y="1927" style="text-anchor:start">-43.21%</text>
|
||||||
|
</g>
|
||||||
|
<text x="100" y="1932" style="text-anchor:start">BenchmarkNextUntilNodes</text>
|
||||||
|
<g style="font-style:italic;font-size:75%">
|
||||||
|
<rect x="612" y="1938" width="147" height="20" style="fill-opacity:0.3;fill:green"/>
|
||||||
|
<text x="764" y="1953" style="text-anchor:start">-49.33%</text>
|
||||||
|
</g>
|
||||||
|
<text x="100" y="1958" style="text-anchor:start">BenchmarkPrevUntil</text>
|
||||||
|
<g style="font-style:italic;font-size:75%">
|
||||||
|
<rect x="612" y="1964" width="111" height="20" style="fill-opacity:0.3;fill:green"/>
|
||||||
|
<text x="728" y="1979" style="text-anchor:start">-37.02%</text>
|
||||||
|
</g>
|
||||||
|
<text x="100" y="1984" style="text-anchor:start">BenchmarkPrevUntilSelection</text>
|
||||||
|
<g style="font-style:italic;font-size:75%">
|
||||||
|
<rect x="612" y="1990" width="133" height="20" style="fill-opacity:0.3;fill:green"/>
|
||||||
|
<text x="750" y="2005" style="text-anchor:start">-44.59%</text>
|
||||||
|
</g>
|
||||||
|
<text x="100" y="2010" style="text-anchor:start">BenchmarkPrevUntilNodes</text>
|
||||||
|
<g style="font-style:italic;font-size:75%">
|
||||||
|
<rect x="612" y="2016" width="173" height="20" style="fill-opacity:0.3;fill:green"/>
|
||||||
|
<text x="790" y="2031" style="text-anchor:start">-57.79%</text>
|
||||||
|
</g>
|
||||||
|
<text x="100" y="2036" style="text-anchor:start">BenchmarkNextFilteredUntil</text>
|
||||||
|
<g style="font-style:italic;font-size:75%">
|
||||||
|
<rect x="612" y="2042" width="109" height="20" style="fill-opacity:0.3;fill:green"/>
|
||||||
|
<text x="726" y="2057" style="text-anchor:start">-36.61%</text>
|
||||||
|
</g>
|
||||||
|
<text x="100" y="2062" style="text-anchor:start">BenchmarkNextFilteredUntilSelection</text>
|
||||||
|
<g style="font-style:italic;font-size:75%">
|
||||||
|
<rect x="612" y="2068" width="113" height="20" style="fill-opacity:0.3;fill:green"/>
|
||||||
|
<text x="730" y="2083" style="text-anchor:start">-37.81%</text>
|
||||||
|
</g>
|
||||||
|
<text x="100" y="2088" style="text-anchor:start">BenchmarkNextFilteredUntilNodes</text>
|
||||||
|
<g style="font-style:italic;font-size:75%">
|
||||||
|
<rect x="612" y="2094" width="177" height="20" style="fill-opacity:0.3;fill:green"/>
|
||||||
|
<text x="794" y="2109" style="text-anchor:start">-59.21%</text>
|
||||||
|
</g>
|
||||||
|
<text x="100" y="2114" style="text-anchor:start">BenchmarkPrevFilteredUntil</text>
|
||||||
|
<g style="font-style:italic;font-size:75%">
|
||||||
|
<rect x="612" y="2120" width="108" height="20" style="fill-opacity:0.3;fill:green"/>
|
||||||
|
<text x="725" y="2135" style="text-anchor:start">-36.20%</text>
|
||||||
|
</g>
|
||||||
|
<text x="100" y="2140" style="text-anchor:start">BenchmarkPrevFilteredUntilSelection</text>
|
||||||
|
<g style="font-style:italic;font-size:75%">
|
||||||
|
<rect x="612" y="2146" width="108" height="20" style="fill-opacity:0.3;fill:green"/>
|
||||||
|
<text x="725" y="2161" style="text-anchor:start">-36.05%</text>
|
||||||
|
</g>
|
||||||
|
<text x="100" y="2166" style="text-anchor:start">BenchmarkPrevFilteredUntilNodes</text>
|
||||||
|
</g>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 21 KiB |
459
Godeps/_workspace/src/github.com/PuerkitoBio/goquery/bench/v0.2.0
generated
vendored
Normal file
459
Godeps/_workspace/src/github.com/PuerkitoBio/goquery/bench/v0.2.0
generated
vendored
Normal file
|
@ -0,0 +1,459 @@
|
||||||
|
PASS
|
||||||
|
BenchmarkFirst 20000000 94.3 ns/op
|
||||||
|
BenchmarkLast 20000000 94.7 ns/op
|
||||||
|
BenchmarkEq 20000000 93.7 ns/op
|
||||||
|
BenchmarkSlice 20000000 89.9 ns/op
|
||||||
|
BenchmarkGet 1000000000 2.72 ns/op
|
||||||
|
BenchmarkIndex 1000000 1834 ns/op
|
||||||
|
--- BENCH: BenchmarkIndex
|
||||||
|
bench_array_test.go:73: Index=3
|
||||||
|
bench_array_test.go:73: Index=3
|
||||||
|
bench_array_test.go:73: Index=3
|
||||||
|
bench_array_test.go:73: Index=3
|
||||||
|
BenchmarkIndexSelector 50000 53958 ns/op
|
||||||
|
--- BENCH: BenchmarkIndexSelector
|
||||||
|
bench_array_test.go:85: IndexSelector=4
|
||||||
|
bench_array_test.go:85: IndexSelector=4
|
||||||
|
bench_array_test.go:85: IndexSelector=4
|
||||||
|
bench_array_test.go:85: IndexSelector=4
|
||||||
|
BenchmarkIndexOfNode 100000000 10.1 ns/op
|
||||||
|
--- BENCH: BenchmarkIndexOfNode
|
||||||
|
bench_array_test.go:99: IndexOfNode=2
|
||||||
|
bench_array_test.go:99: IndexOfNode=2
|
||||||
|
bench_array_test.go:99: IndexOfNode=2
|
||||||
|
bench_array_test.go:99: IndexOfNode=2
|
||||||
|
bench_array_test.go:99: IndexOfNode=2
|
||||||
|
BenchmarkIndexOfSelection 100000000 10.9 ns/op
|
||||||
|
--- BENCH: BenchmarkIndexOfSelection
|
||||||
|
bench_array_test.go:111: IndexOfSelection=2
|
||||||
|
bench_array_test.go:111: IndexOfSelection=2
|
||||||
|
bench_array_test.go:111: IndexOfSelection=2
|
||||||
|
bench_array_test.go:111: IndexOfSelection=2
|
||||||
|
bench_array_test.go:111: IndexOfSelection=2
|
||||||
|
BenchmarkMetalReviewExample 5000 326712 ns/op
|
||||||
|
--- BENCH: BenchmarkMetalReviewExample
|
||||||
|
bench_example_test.go:40: Review 0: Midnight - Complete and Total Hell (8.5).
|
||||||
|
Review 1: Over Your Threshold - Facticity (6.0).
|
||||||
|
Review 2: Nuclear Death Terror - Chaos Reigns (7.5).
|
||||||
|
Review 3: Evoken - Atra Mors (9.5).
|
||||||
|
|
||||||
|
bench_example_test.go:41: MetalReviewExample=10
|
||||||
|
bench_example_test.go:40: Review 0: Midnight - Complete and Total Hell (8.5).
|
||||||
|
Review 1: Over Your Threshold - Facticity (6.0).
|
||||||
|
Review 2: Nuclear Death Terror - Chaos Reigns (7.5).
|
||||||
|
Review 3: Evoken - Atra Mors (9.5).
|
||||||
|
... [output truncated]
|
||||||
|
BenchmarkAdd 50000 51776 ns/op
|
||||||
|
--- BENCH: BenchmarkAdd
|
||||||
|
bench_expand_test.go:20: Add=43
|
||||||
|
bench_expand_test.go:20: Add=43
|
||||||
|
bench_expand_test.go:20: Add=43
|
||||||
|
bench_expand_test.go:20: Add=43
|
||||||
|
BenchmarkAddSelection 10000000 196 ns/op
|
||||||
|
--- BENCH: BenchmarkAddSelection
|
||||||
|
bench_expand_test.go:37: AddSelection=43
|
||||||
|
bench_expand_test.go:37: AddSelection=43
|
||||||
|
bench_expand_test.go:37: AddSelection=43
|
||||||
|
bench_expand_test.go:37: AddSelection=43
|
||||||
|
bench_expand_test.go:37: AddSelection=43
|
||||||
|
BenchmarkAddNodes 10000000 191 ns/op
|
||||||
|
--- BENCH: BenchmarkAddNodes
|
||||||
|
bench_expand_test.go:55: AddNodes=43
|
||||||
|
bench_expand_test.go:55: AddNodes=43
|
||||||
|
bench_expand_test.go:55: AddNodes=43
|
||||||
|
bench_expand_test.go:55: AddNodes=43
|
||||||
|
bench_expand_test.go:55: AddNodes=43
|
||||||
|
BenchmarkAndSelf 1000000 2495 ns/op
|
||||||
|
--- BENCH: BenchmarkAndSelf
|
||||||
|
bench_expand_test.go:71: AndSelf=44
|
||||||
|
bench_expand_test.go:71: AndSelf=44
|
||||||
|
bench_expand_test.go:71: AndSelf=44
|
||||||
|
bench_expand_test.go:71: AndSelf=44
|
||||||
|
BenchmarkFilter 50000 30974 ns/op
|
||||||
|
--- BENCH: BenchmarkFilter
|
||||||
|
bench_filter_test.go:20: Filter=13
|
||||||
|
bench_filter_test.go:20: Filter=13
|
||||||
|
bench_filter_test.go:20: Filter=13
|
||||||
|
bench_filter_test.go:20: Filter=13
|
||||||
|
BenchmarkNot 50000 35322 ns/op
|
||||||
|
--- BENCH: BenchmarkNot
|
||||||
|
bench_filter_test.go:36: Not=371
|
||||||
|
bench_filter_test.go:36: Not=371
|
||||||
|
bench_filter_test.go:36: Not=371
|
||||||
|
bench_filter_test.go:36: Not=371
|
||||||
|
BenchmarkFilterFunction 50000 65644 ns/op
|
||||||
|
--- BENCH: BenchmarkFilterFunction
|
||||||
|
bench_filter_test.go:55: FilterFunction=112
|
||||||
|
bench_filter_test.go:55: FilterFunction=112
|
||||||
|
bench_filter_test.go:55: FilterFunction=112
|
||||||
|
bench_filter_test.go:55: FilterFunction=112
|
||||||
|
BenchmarkNotFunction 50000 69245 ns/op
|
||||||
|
--- BENCH: BenchmarkNotFunction
|
||||||
|
bench_filter_test.go:74: NotFunction=261
|
||||||
|
bench_filter_test.go:74: NotFunction=261
|
||||||
|
bench_filter_test.go:74: NotFunction=261
|
||||||
|
bench_filter_test.go:74: NotFunction=261
|
||||||
|
BenchmarkFilterNodes 50000 64824 ns/op
|
||||||
|
--- BENCH: BenchmarkFilterNodes
|
||||||
|
bench_filter_test.go:92: FilterNodes=2
|
||||||
|
bench_filter_test.go:92: FilterNodes=2
|
||||||
|
bench_filter_test.go:92: FilterNodes=2
|
||||||
|
bench_filter_test.go:92: FilterNodes=2
|
||||||
|
BenchmarkNotNodes 20000 76247 ns/op
|
||||||
|
--- BENCH: BenchmarkNotNodes
|
||||||
|
bench_filter_test.go:110: NotNodes=360
|
||||||
|
bench_filter_test.go:110: NotNodes=360
|
||||||
|
bench_filter_test.go:110: NotNodes=360
|
||||||
|
bench_filter_test.go:110: NotNodes=360
|
||||||
|
BenchmarkFilterSelection 50000 66154 ns/op
|
||||||
|
--- BENCH: BenchmarkFilterSelection
|
||||||
|
bench_filter_test.go:127: FilterSelection=2
|
||||||
|
bench_filter_test.go:127: FilterSelection=2
|
||||||
|
bench_filter_test.go:127: FilterSelection=2
|
||||||
|
bench_filter_test.go:127: FilterSelection=2
|
||||||
|
BenchmarkNotSelection 20000 76336 ns/op
|
||||||
|
--- BENCH: BenchmarkNotSelection
|
||||||
|
bench_filter_test.go:144: NotSelection=360
|
||||||
|
bench_filter_test.go:144: NotSelection=360
|
||||||
|
bench_filter_test.go:144: NotSelection=360
|
||||||
|
bench_filter_test.go:144: NotSelection=360
|
||||||
|
BenchmarkHas 5000 569495 ns/op
|
||||||
|
--- BENCH: BenchmarkHas
|
||||||
|
bench_filter_test.go:160: Has=13
|
||||||
|
bench_filter_test.go:160: Has=13
|
||||||
|
bench_filter_test.go:160: Has=13
|
||||||
|
BenchmarkHasNodes 10000 227059 ns/op
|
||||||
|
--- BENCH: BenchmarkHasNodes
|
||||||
|
bench_filter_test.go:178: HasNodes=15
|
||||||
|
bench_filter_test.go:178: HasNodes=15
|
||||||
|
bench_filter_test.go:178: HasNodes=15
|
||||||
|
BenchmarkHasSelection 10000 227167 ns/op
|
||||||
|
--- BENCH: BenchmarkHasSelection
|
||||||
|
bench_filter_test.go:195: HasSelection=15
|
||||||
|
bench_filter_test.go:195: HasSelection=15
|
||||||
|
bench_filter_test.go:195: HasSelection=15
|
||||||
|
BenchmarkEnd 500000000 3.99 ns/op
|
||||||
|
--- BENCH: BenchmarkEnd
|
||||||
|
bench_filter_test.go:211: End=373
|
||||||
|
bench_filter_test.go:211: End=373
|
||||||
|
bench_filter_test.go:211: End=373
|
||||||
|
bench_filter_test.go:211: End=373
|
||||||
|
bench_filter_test.go:211: End=373
|
||||||
|
bench_filter_test.go:211: End=373
|
||||||
|
BenchmarkEach 200000 9354 ns/op
|
||||||
|
--- BENCH: BenchmarkEach
|
||||||
|
bench_iteration_test.go:22: Each=59
|
||||||
|
bench_iteration_test.go:22: Each=59
|
||||||
|
bench_iteration_test.go:22: Each=59
|
||||||
|
bench_iteration_test.go:22: Each=59
|
||||||
|
BenchmarkMap 100000 16557 ns/op
|
||||||
|
--- BENCH: BenchmarkMap
|
||||||
|
bench_iteration_test.go:41: Map=59
|
||||||
|
bench_iteration_test.go:41: Map=59
|
||||||
|
bench_iteration_test.go:41: Map=59
|
||||||
|
bench_iteration_test.go:41: Map=59
|
||||||
|
BenchmarkAttr 50000000 36.4 ns/op
|
||||||
|
--- BENCH: BenchmarkAttr
|
||||||
|
bench_property_test.go:16: Attr=firstHeading
|
||||||
|
bench_property_test.go:16: Attr=firstHeading
|
||||||
|
bench_property_test.go:16: Attr=firstHeading
|
||||||
|
bench_property_test.go:16: Attr=firstHeading
|
||||||
|
bench_property_test.go:16: Attr=firstHeading
|
||||||
|
BenchmarkText 100000 18473 ns/op
|
||||||
|
BenchmarkLength 2000000000 0.76 ns/op
|
||||||
|
--- BENCH: BenchmarkLength
|
||||||
|
bench_property_test.go:37: Length=14
|
||||||
|
bench_property_test.go:37: Length=14
|
||||||
|
bench_property_test.go:37: Length=14
|
||||||
|
bench_property_test.go:37: Length=14
|
||||||
|
bench_property_test.go:37: Length=14
|
||||||
|
bench_property_test.go:37: Length=14
|
||||||
|
BenchmarkHtml 5000000 666 ns/op
|
||||||
|
BenchmarkIs 50000 35174 ns/op
|
||||||
|
--- BENCH: BenchmarkIs
|
||||||
|
bench_query_test.go:16: Is=true
|
||||||
|
bench_query_test.go:16: Is=true
|
||||||
|
bench_query_test.go:16: Is=true
|
||||||
|
bench_query_test.go:16: Is=true
|
||||||
|
BenchmarkIsPositional 50000 31814 ns/op
|
||||||
|
--- BENCH: BenchmarkIsPositional
|
||||||
|
bench_query_test.go:28: IsPositional=true
|
||||||
|
bench_query_test.go:28: IsPositional=true
|
||||||
|
bench_query_test.go:28: IsPositional=true
|
||||||
|
bench_query_test.go:28: IsPositional=true
|
||||||
|
BenchmarkIsFunction 1000000 2754 ns/op
|
||||||
|
--- BENCH: BenchmarkIsFunction
|
||||||
|
bench_query_test.go:43: IsFunction=true
|
||||||
|
bench_query_test.go:43: IsFunction=true
|
||||||
|
bench_query_test.go:43: IsFunction=true
|
||||||
|
bench_query_test.go:43: IsFunction=true
|
||||||
|
BenchmarkIsSelection 50000 66260 ns/op
|
||||||
|
--- BENCH: BenchmarkIsSelection
|
||||||
|
bench_query_test.go:56: IsSelection=true
|
||||||
|
bench_query_test.go:56: IsSelection=true
|
||||||
|
bench_query_test.go:56: IsSelection=true
|
||||||
|
bench_query_test.go:56: IsSelection=true
|
||||||
|
BenchmarkIsNodes 50000 64682 ns/op
|
||||||
|
--- BENCH: BenchmarkIsNodes
|
||||||
|
bench_query_test.go:70: IsNodes=true
|
||||||
|
bench_query_test.go:70: IsNodes=true
|
||||||
|
bench_query_test.go:70: IsNodes=true
|
||||||
|
bench_query_test.go:70: IsNodes=true
|
||||||
|
BenchmarkHasClass 5000 672953 ns/op
|
||||||
|
--- BENCH: BenchmarkHasClass
|
||||||
|
bench_query_test.go:82: HasClass=true
|
||||||
|
bench_query_test.go:82: HasClass=true
|
||||||
|
bench_query_test.go:82: HasClass=true
|
||||||
|
BenchmarkContains 100000000 11.3 ns/op
|
||||||
|
--- BENCH: BenchmarkContains
|
||||||
|
bench_query_test.go:96: Contains=true
|
||||||
|
bench_query_test.go:96: Contains=true
|
||||||
|
bench_query_test.go:96: Contains=true
|
||||||
|
bench_query_test.go:96: Contains=true
|
||||||
|
bench_query_test.go:96: Contains=true
|
||||||
|
BenchmarkFind 50000 53780 ns/op
|
||||||
|
--- BENCH: BenchmarkFind
|
||||||
|
bench_traversal_test.go:18: Find=41
|
||||||
|
bench_traversal_test.go:18: Find=41
|
||||||
|
bench_traversal_test.go:18: Find=41
|
||||||
|
bench_traversal_test.go:18: Find=41
|
||||||
|
BenchmarkFindWithinSelection 10000 125963 ns/op
|
||||||
|
--- BENCH: BenchmarkFindWithinSelection
|
||||||
|
bench_traversal_test.go:34: FindWithinSelection=39
|
||||||
|
bench_traversal_test.go:34: FindWithinSelection=39
|
||||||
|
bench_traversal_test.go:34: FindWithinSelection=39
|
||||||
|
BenchmarkFindSelection 5000 357318 ns/op
|
||||||
|
--- BENCH: BenchmarkFindSelection
|
||||||
|
bench_traversal_test.go:51: FindSelection=73
|
||||||
|
bench_traversal_test.go:51: FindSelection=73
|
||||||
|
bench_traversal_test.go:51: FindSelection=73
|
||||||
|
BenchmarkFindNodes 5000 357587 ns/op
|
||||||
|
--- BENCH: BenchmarkFindNodes
|
||||||
|
bench_traversal_test.go:69: FindNodes=73
|
||||||
|
bench_traversal_test.go:69: FindNodes=73
|
||||||
|
bench_traversal_test.go:69: FindNodes=73
|
||||||
|
BenchmarkContents 200000 9135 ns/op
|
||||||
|
--- BENCH: BenchmarkContents
|
||||||
|
bench_traversal_test.go:85: Contents=16
|
||||||
|
bench_traversal_test.go:85: Contents=16
|
||||||
|
bench_traversal_test.go:85: Contents=16
|
||||||
|
bench_traversal_test.go:85: Contents=16
|
||||||
|
BenchmarkContentsFiltered 200000 12383 ns/op
|
||||||
|
--- BENCH: BenchmarkContentsFiltered
|
||||||
|
bench_traversal_test.go:101: ContentsFiltered=1
|
||||||
|
bench_traversal_test.go:101: ContentsFiltered=1
|
||||||
|
bench_traversal_test.go:101: ContentsFiltered=1
|
||||||
|
bench_traversal_test.go:101: ContentsFiltered=1
|
||||||
|
BenchmarkChildren 1000000 1809 ns/op
|
||||||
|
--- BENCH: BenchmarkChildren
|
||||||
|
bench_traversal_test.go:117: Children=2
|
||||||
|
bench_traversal_test.go:117: Children=2
|
||||||
|
bench_traversal_test.go:117: Children=2
|
||||||
|
bench_traversal_test.go:117: Children=2
|
||||||
|
BenchmarkChildrenFiltered 500000 5814 ns/op
|
||||||
|
--- BENCH: BenchmarkChildrenFiltered
|
||||||
|
bench_traversal_test.go:133: ChildrenFiltered=2
|
||||||
|
bench_traversal_test.go:133: ChildrenFiltered=2
|
||||||
|
bench_traversal_test.go:133: ChildrenFiltered=2
|
||||||
|
bench_traversal_test.go:133: ChildrenFiltered=2
|
||||||
|
BenchmarkParent 50000 44810 ns/op
|
||||||
|
--- BENCH: BenchmarkParent
|
||||||
|
bench_traversal_test.go:149: Parent=55
|
||||||
|
bench_traversal_test.go:149: Parent=55
|
||||||
|
bench_traversal_test.go:149: Parent=55
|
||||||
|
bench_traversal_test.go:149: Parent=55
|
||||||
|
BenchmarkParentFiltered 50000 48795 ns/op
|
||||||
|
--- BENCH: BenchmarkParentFiltered
|
||||||
|
bench_traversal_test.go:165: ParentFiltered=4
|
||||||
|
bench_traversal_test.go:165: ParentFiltered=4
|
||||||
|
bench_traversal_test.go:165: ParentFiltered=4
|
||||||
|
bench_traversal_test.go:165: ParentFiltered=4
|
||||||
|
BenchmarkParents 20000 89102 ns/op
|
||||||
|
--- BENCH: BenchmarkParents
|
||||||
|
bench_traversal_test.go:181: Parents=73
|
||||||
|
bench_traversal_test.go:181: Parents=73
|
||||||
|
bench_traversal_test.go:181: Parents=73
|
||||||
|
bench_traversal_test.go:181: Parents=73
|
||||||
|
BenchmarkParentsFiltered 20000 93953 ns/op
|
||||||
|
--- BENCH: BenchmarkParentsFiltered
|
||||||
|
bench_traversal_test.go:197: ParentsFiltered=18
|
||||||
|
bench_traversal_test.go:197: ParentsFiltered=18
|
||||||
|
bench_traversal_test.go:197: ParentsFiltered=18
|
||||||
|
bench_traversal_test.go:197: ParentsFiltered=18
|
||||||
|
BenchmarkParentsUntil 10000 130783 ns/op
|
||||||
|
--- BENCH: BenchmarkParentsUntil
|
||||||
|
bench_traversal_test.go:213: ParentsUntil=52
|
||||||
|
bench_traversal_test.go:213: ParentsUntil=52
|
||||||
|
bench_traversal_test.go:213: ParentsUntil=52
|
||||||
|
BenchmarkParentsUntilSelection 10000 231797 ns/op
|
||||||
|
--- BENCH: BenchmarkParentsUntilSelection
|
||||||
|
bench_traversal_test.go:230: ParentsUntilSelection=70
|
||||||
|
bench_traversal_test.go:230: ParentsUntilSelection=70
|
||||||
|
bench_traversal_test.go:230: ParentsUntilSelection=70
|
||||||
|
BenchmarkParentsUntilNodes 10000 233761 ns/op
|
||||||
|
--- BENCH: BenchmarkParentsUntilNodes
|
||||||
|
bench_traversal_test.go:248: ParentsUntilNodes=70
|
||||||
|
bench_traversal_test.go:248: ParentsUntilNodes=70
|
||||||
|
bench_traversal_test.go:248: ParentsUntilNodes=70
|
||||||
|
BenchmarkParentsFilteredUntil 50000 31360 ns/op
|
||||||
|
--- BENCH: BenchmarkParentsFilteredUntil
|
||||||
|
bench_traversal_test.go:264: ParentsFilteredUntil=2
|
||||||
|
bench_traversal_test.go:264: ParentsFilteredUntil=2
|
||||||
|
bench_traversal_test.go:264: ParentsFilteredUntil=2
|
||||||
|
bench_traversal_test.go:264: ParentsFilteredUntil=2
|
||||||
|
BenchmarkParentsFilteredUntilSelection 50000 30272 ns/op
|
||||||
|
--- BENCH: BenchmarkParentsFilteredUntilSelection
|
||||||
|
bench_traversal_test.go:281: ParentsFilteredUntilSelection=2
|
||||||
|
bench_traversal_test.go:281: ParentsFilteredUntilSelection=2
|
||||||
|
bench_traversal_test.go:281: ParentsFilteredUntilSelection=2
|
||||||
|
bench_traversal_test.go:281: ParentsFilteredUntilSelection=2
|
||||||
|
BenchmarkParentsFilteredUntilNodes 50000 30327 ns/op
|
||||||
|
--- BENCH: BenchmarkParentsFilteredUntilNodes
|
||||||
|
bench_traversal_test.go:299: ParentsFilteredUntilNodes=2
|
||||||
|
bench_traversal_test.go:299: ParentsFilteredUntilNodes=2
|
||||||
|
bench_traversal_test.go:299: ParentsFilteredUntilNodes=2
|
||||||
|
bench_traversal_test.go:299: ParentsFilteredUntilNodes=2
|
||||||
|
BenchmarkSiblings 20000 89862 ns/op
|
||||||
|
--- BENCH: BenchmarkSiblings
|
||||||
|
bench_traversal_test.go:315: Siblings=293
|
||||||
|
bench_traversal_test.go:315: Siblings=293
|
||||||
|
bench_traversal_test.go:315: Siblings=293
|
||||||
|
bench_traversal_test.go:315: Siblings=293
|
||||||
|
BenchmarkSiblingsFiltered 20000 97948 ns/op
|
||||||
|
--- BENCH: BenchmarkSiblingsFiltered
|
||||||
|
bench_traversal_test.go:331: SiblingsFiltered=46
|
||||||
|
bench_traversal_test.go:331: SiblingsFiltered=46
|
||||||
|
bench_traversal_test.go:331: SiblingsFiltered=46
|
||||||
|
bench_traversal_test.go:331: SiblingsFiltered=46
|
||||||
|
BenchmarkNext 50000 31975 ns/op
|
||||||
|
--- BENCH: BenchmarkNext
|
||||||
|
bench_traversal_test.go:347: Next=49
|
||||||
|
bench_traversal_test.go:347: Next=49
|
||||||
|
bench_traversal_test.go:347: Next=49
|
||||||
|
bench_traversal_test.go:347: Next=49
|
||||||
|
BenchmarkNextFiltered 50000 34887 ns/op
|
||||||
|
--- BENCH: BenchmarkNextFiltered
|
||||||
|
bench_traversal_test.go:363: NextFiltered=6
|
||||||
|
bench_traversal_test.go:363: NextFiltered=6
|
||||||
|
bench_traversal_test.go:363: NextFiltered=6
|
||||||
|
bench_traversal_test.go:363: NextFiltered=6
|
||||||
|
BenchmarkNextAll 50000 60734 ns/op
|
||||||
|
--- BENCH: BenchmarkNextAll
|
||||||
|
bench_traversal_test.go:379: NextAll=234
|
||||||
|
bench_traversal_test.go:379: NextAll=234
|
||||||
|
bench_traversal_test.go:379: NextAll=234
|
||||||
|
bench_traversal_test.go:379: NextAll=234
|
||||||
|
BenchmarkNextAllFiltered 50000 67428 ns/op
|
||||||
|
--- BENCH: BenchmarkNextAllFiltered
|
||||||
|
bench_traversal_test.go:395: NextAllFiltered=33
|
||||||
|
bench_traversal_test.go:395: NextAllFiltered=33
|
||||||
|
bench_traversal_test.go:395: NextAllFiltered=33
|
||||||
|
bench_traversal_test.go:395: NextAllFiltered=33
|
||||||
|
BenchmarkPrev 50000 32399 ns/op
|
||||||
|
--- BENCH: BenchmarkPrev
|
||||||
|
bench_traversal_test.go:411: Prev=49
|
||||||
|
bench_traversal_test.go:411: Prev=49
|
||||||
|
bench_traversal_test.go:411: Prev=49
|
||||||
|
bench_traversal_test.go:411: Prev=49
|
||||||
|
BenchmarkPrevFiltered 50000 34944 ns/op
|
||||||
|
--- BENCH: BenchmarkPrevFiltered
|
||||||
|
bench_traversal_test.go:429: PrevFiltered=7
|
||||||
|
bench_traversal_test.go:429: PrevFiltered=7
|
||||||
|
bench_traversal_test.go:429: PrevFiltered=7
|
||||||
|
bench_traversal_test.go:429: PrevFiltered=7
|
||||||
|
BenchmarkPrevAll 100000 29360 ns/op
|
||||||
|
--- BENCH: BenchmarkPrevAll
|
||||||
|
bench_traversal_test.go:445: PrevAll=78
|
||||||
|
bench_traversal_test.go:445: PrevAll=78
|
||||||
|
bench_traversal_test.go:445: PrevAll=78
|
||||||
|
bench_traversal_test.go:445: PrevAll=78
|
||||||
|
BenchmarkPrevAllFiltered 50000 32291 ns/op
|
||||||
|
--- BENCH: BenchmarkPrevAllFiltered
|
||||||
|
bench_traversal_test.go:461: PrevAllFiltered=6
|
||||||
|
bench_traversal_test.go:461: PrevAllFiltered=6
|
||||||
|
bench_traversal_test.go:461: PrevAllFiltered=6
|
||||||
|
bench_traversal_test.go:461: PrevAllFiltered=6
|
||||||
|
BenchmarkNextUntil 10000 191890 ns/op
|
||||||
|
--- BENCH: BenchmarkNextUntil
|
||||||
|
bench_traversal_test.go:477: NextUntil=84
|
||||||
|
bench_traversal_test.go:477: NextUntil=84
|
||||||
|
bench_traversal_test.go:477: NextUntil=84
|
||||||
|
BenchmarkNextUntilSelection 20000 92054 ns/op
|
||||||
|
--- BENCH: BenchmarkNextUntilSelection
|
||||||
|
bench_traversal_test.go:494: NextUntilSelection=42
|
||||||
|
bench_traversal_test.go:494: NextUntilSelection=42
|
||||||
|
bench_traversal_test.go:494: NextUntilSelection=42
|
||||||
|
bench_traversal_test.go:494: NextUntilSelection=42
|
||||||
|
BenchmarkNextUntilNodes 50000 43401 ns/op
|
||||||
|
--- BENCH: BenchmarkNextUntilNodes
|
||||||
|
bench_traversal_test.go:512: NextUntilNodes=12
|
||||||
|
bench_traversal_test.go:512: NextUntilNodes=12
|
||||||
|
bench_traversal_test.go:512: NextUntilNodes=12
|
||||||
|
bench_traversal_test.go:512: NextUntilNodes=12
|
||||||
|
BenchmarkPrevUntil 5000 433383 ns/op
|
||||||
|
--- BENCH: BenchmarkPrevUntil
|
||||||
|
bench_traversal_test.go:528: PrevUntil=238
|
||||||
|
bench_traversal_test.go:528: PrevUntil=238
|
||||||
|
bench_traversal_test.go:528: PrevUntil=238
|
||||||
|
BenchmarkPrevUntilSelection 10000 116423 ns/op
|
||||||
|
--- BENCH: BenchmarkPrevUntilSelection
|
||||||
|
bench_traversal_test.go:545: PrevUntilSelection=49
|
||||||
|
bench_traversal_test.go:545: PrevUntilSelection=49
|
||||||
|
bench_traversal_test.go:545: PrevUntilSelection=49
|
||||||
|
BenchmarkPrevUntilNodes 50000 35338 ns/op
|
||||||
|
--- BENCH: BenchmarkPrevUntilNodes
|
||||||
|
bench_traversal_test.go:563: PrevUntilNodes=11
|
||||||
|
bench_traversal_test.go:563: PrevUntilNodes=11
|
||||||
|
bench_traversal_test.go:563: PrevUntilNodes=11
|
||||||
|
bench_traversal_test.go:563: PrevUntilNodes=11
|
||||||
|
BenchmarkNextFilteredUntil 10000 104686 ns/op
|
||||||
|
--- BENCH: BenchmarkNextFilteredUntil
|
||||||
|
bench_traversal_test.go:579: NextFilteredUntil=22
|
||||||
|
bench_traversal_test.go:579: NextFilteredUntil=22
|
||||||
|
bench_traversal_test.go:579: NextFilteredUntil=22
|
||||||
|
BenchmarkNextFilteredUntilSelection 20000 99485 ns/op
|
||||||
|
--- BENCH: BenchmarkNextFilteredUntilSelection
|
||||||
|
bench_traversal_test.go:596: NextFilteredUntilSelection=22
|
||||||
|
bench_traversal_test.go:596: NextFilteredUntilSelection=22
|
||||||
|
bench_traversal_test.go:596: NextFilteredUntilSelection=22
|
||||||
|
bench_traversal_test.go:596: NextFilteredUntilSelection=22
|
||||||
|
BenchmarkNextFilteredUntilNodes 20000 99452 ns/op
|
||||||
|
--- BENCH: BenchmarkNextFilteredUntilNodes
|
||||||
|
bench_traversal_test.go:614: NextFilteredUntilNodes=22
|
||||||
|
bench_traversal_test.go:614: NextFilteredUntilNodes=22
|
||||||
|
bench_traversal_test.go:614: NextFilteredUntilNodes=22
|
||||||
|
bench_traversal_test.go:614: NextFilteredUntilNodes=22
|
||||||
|
BenchmarkPrevFilteredUntil 10000 112640 ns/op
|
||||||
|
--- BENCH: BenchmarkPrevFilteredUntil
|
||||||
|
bench_traversal_test.go:630: PrevFilteredUntil=20
|
||||||
|
bench_traversal_test.go:630: PrevFilteredUntil=20
|
||||||
|
bench_traversal_test.go:630: PrevFilteredUntil=20
|
||||||
|
BenchmarkPrevFilteredUntilSelection 10000 103702 ns/op
|
||||||
|
--- BENCH: BenchmarkPrevFilteredUntilSelection
|
||||||
|
bench_traversal_test.go:647: PrevFilteredUntilSelection=20
|
||||||
|
bench_traversal_test.go:647: PrevFilteredUntilSelection=20
|
||||||
|
bench_traversal_test.go:647: PrevFilteredUntilSelection=20
|
||||||
|
BenchmarkPrevFilteredUntilNodes 10000 103277 ns/op
|
||||||
|
--- BENCH: BenchmarkPrevFilteredUntilNodes
|
||||||
|
bench_traversal_test.go:665: PrevFilteredUntilNodes=20
|
||||||
|
bench_traversal_test.go:665: PrevFilteredUntilNodes=20
|
||||||
|
bench_traversal_test.go:665: PrevFilteredUntilNodes=20
|
||||||
|
BenchmarkClosest 500000 6530 ns/op
|
||||||
|
--- BENCH: BenchmarkClosest
|
||||||
|
bench_traversal_test.go:681: Closest=2
|
||||||
|
bench_traversal_test.go:681: Closest=2
|
||||||
|
bench_traversal_test.go:681: Closest=2
|
||||||
|
bench_traversal_test.go:681: Closest=2
|
||||||
|
BenchmarkClosestSelection 1000000 1135 ns/op
|
||||||
|
--- BENCH: BenchmarkClosestSelection
|
||||||
|
bench_traversal_test.go:698: ClosestSelection=2
|
||||||
|
bench_traversal_test.go:698: ClosestSelection=2
|
||||||
|
bench_traversal_test.go:698: ClosestSelection=2
|
||||||
|
bench_traversal_test.go:698: ClosestSelection=2
|
||||||
|
BenchmarkClosestNodes 1000000 1133 ns/op
|
||||||
|
--- BENCH: BenchmarkClosestNodes
|
||||||
|
bench_traversal_test.go:715: ClosestNodes=2
|
||||||
|
bench_traversal_test.go:715: ClosestNodes=2
|
||||||
|
bench_traversal_test.go:715: ClosestNodes=2
|
||||||
|
bench_traversal_test.go:715: ClosestNodes=2
|
||||||
|
ok github.com/PuerkitoBio/goquery 192.541s
|
420
Godeps/_workspace/src/github.com/PuerkitoBio/goquery/bench/v0.2.0-v0.2.1-go1.1rc1.svg
generated
vendored
Normal file
420
Godeps/_workspace/src/github.com/PuerkitoBio/goquery/bench/v0.2.0-v0.2.1-go1.1rc1.svg
generated
vendored
Normal file
|
@ -0,0 +1,420 @@
|
||||||
|
<?xml version="1.0"?>
|
||||||
|
<!-- Generated by SVGo -->
|
||||||
|
<svg width="1024" height="768"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||||
|
<g style="font-size:20px;font-family:sans-serif">
|
||||||
|
<rect x="0" y="0" width="1024" height="768" style="fill:white"/>
|
||||||
|
<text x="100" y="50" style="font-size:150%"></text>
|
||||||
|
<g style="font-style:italic;font-size:75%">
|
||||||
|
<rect x="606" y="118" width="6" height="20" style="fill-opacity:0.3;fill:red"/>
|
||||||
|
<text x="601" y="133" style="text-anchor:end">+2.12%</text>
|
||||||
|
</g>
|
||||||
|
<text x="100" y="138" style="text-anchor:start">BenchmarkFirst</text>
|
||||||
|
<g style="font-style:italic;font-size:75%">
|
||||||
|
<rect x="609" y="144" width="3" height="20" style="fill-opacity:0.3;fill:red"/>
|
||||||
|
<text x="604" y="159" style="text-anchor:end">+1.06%</text>
|
||||||
|
</g>
|
||||||
|
<text x="100" y="164" style="text-anchor:start">BenchmarkLast</text>
|
||||||
|
<g style="font-style:italic;font-size:75%">
|
||||||
|
<rect x="602" y="170" width="10" height="20" style="fill-opacity:0.3;fill:red"/>
|
||||||
|
<text x="597" y="185" style="text-anchor:end">+3.63%</text>
|
||||||
|
</g>
|
||||||
|
<text x="100" y="190" style="text-anchor:start">BenchmarkEq</text>
|
||||||
|
<g style="font-style:italic;font-size:75%">
|
||||||
|
<rect x="604" y="196" width="8" height="20" style="fill-opacity:0.3;fill:red"/>
|
||||||
|
<text x="599" y="211" style="text-anchor:end">+2.67%</text>
|
||||||
|
</g>
|
||||||
|
<text x="100" y="216" style="text-anchor:start">BenchmarkSlice</text>
|
||||||
|
<g style="font-style:italic;font-size:75%">
|
||||||
|
<rect x="612" y="222" width="72" height="20" style="fill-opacity:0.3;fill:green"/>
|
||||||
|
<text x="689" y="237" style="text-anchor:start">-24.26%</text>
|
||||||
|
</g>
|
||||||
|
<text x="100" y="242" style="text-anchor:start">BenchmarkGet</text>
|
||||||
|
<g style="font-style:italic;font-size:75%">
|
||||||
|
<rect x="612" y="248" width="125" height="20" style="fill-opacity:0.3;fill:green"/>
|
||||||
|
<text x="742" y="263" style="text-anchor:start">-41.71%</text>
|
||||||
|
</g>
|
||||||
|
<text x="100" y="268" style="text-anchor:start">BenchmarkIndex</text>
|
||||||
|
<g style="font-style:italic;font-size:75%">
|
||||||
|
<rect x="612" y="274" width="151" height="20" style="fill-opacity:0.3;fill:green"/>
|
||||||
|
<text x="768" y="289" style="text-anchor:start">-50.42%</text>
|
||||||
|
</g>
|
||||||
|
<text x="100" y="294" style="text-anchor:start">BenchmarkIndexSelector</text>
|
||||||
|
<g style="font-style:italic;font-size:75%">
|
||||||
|
<rect x="595" y="300" width="17" height="20" style="fill-opacity:0.3;fill:red"/>
|
||||||
|
<text x="590" y="315" style="text-anchor:end">+5.94%</text>
|
||||||
|
</g>
|
||||||
|
<text x="100" y="320" style="text-anchor:start">BenchmarkIndexOfNode</text>
|
||||||
|
<g style="font-style:italic;font-size:75%">
|
||||||
|
<rect x="588" y="326" width="24" height="20" style="fill-opacity:0.3;fill:red"/>
|
||||||
|
<text x="583" y="341" style="text-anchor:end">+8.26%</text>
|
||||||
|
</g>
|
||||||
|
<text x="100" y="346" style="text-anchor:start">BenchmarkIndexOfSelection</text>
|
||||||
|
<g style="font-style:italic;font-size:75%">
|
||||||
|
<rect x="612" y="352" width="98" height="20" style="fill-opacity:0.3;fill:green"/>
|
||||||
|
<text x="715" y="367" style="text-anchor:start">-32.94%</text>
|
||||||
|
</g>
|
||||||
|
<text x="100" y="372" style="text-anchor:start">BenchmarkMetalReviewExample</text>
|
||||||
|
<g style="font-style:italic;font-size:75%">
|
||||||
|
<rect x="612" y="378" width="170" height="20" style="fill-opacity:0.3;fill:green"/>
|
||||||
|
<text x="787" y="393" style="text-anchor:start">-56.84%</text>
|
||||||
|
</g>
|
||||||
|
<text x="100" y="398" style="text-anchor:start">BenchmarkAdd</text>
|
||||||
|
<g style="font-style:italic;font-size:75%">
|
||||||
|
<rect x="593" y="404" width="19" height="20" style="fill-opacity:0.3;fill:red"/>
|
||||||
|
<text x="588" y="419" style="text-anchor:end">+6.63%</text>
|
||||||
|
</g>
|
||||||
|
<text x="100" y="424" style="text-anchor:start">BenchmarkAddSelection</text>
|
||||||
|
<g style="font-style:italic;font-size:75%">
|
||||||
|
<rect x="584" y="430" width="28" height="20" style="fill-opacity:0.3;fill:red"/>
|
||||||
|
<text x="579" y="445" style="text-anchor:end">+9.42%</text>
|
||||||
|
</g>
|
||||||
|
<text x="100" y="450" style="text-anchor:start">BenchmarkAddNodes</text>
|
||||||
|
<g style="font-style:italic;font-size:75%">
|
||||||
|
<rect x="604" y="456" width="8" height="20" style="fill-opacity:0.3;fill:red"/>
|
||||||
|
<text x="599" y="471" style="text-anchor:end">+2.93%</text>
|
||||||
|
</g>
|
||||||
|
<text x="100" y="476" style="text-anchor:start">BenchmarkAndSelf</text>
|
||||||
|
<g style="font-style:italic;font-size:75%">
|
||||||
|
<rect x="612" y="482" width="41" height="20" style="fill-opacity:0.3;fill:green"/>
|
||||||
|
<text x="658" y="497" style="text-anchor:start">-13.75%</text>
|
||||||
|
</g>
|
||||||
|
<text x="100" y="502" style="text-anchor:start">BenchmarkFilter</text>
|
||||||
|
<g style="font-style:italic;font-size:75%">
|
||||||
|
<rect x="612" y="508" width="44" height="20" style="fill-opacity:0.3;fill:green"/>
|
||||||
|
<text x="661" y="523" style="text-anchor:start">-14.90%</text>
|
||||||
|
</g>
|
||||||
|
<text x="100" y="528" style="text-anchor:start">BenchmarkNot</text>
|
||||||
|
<g style="font-style:italic;font-size:75%">
|
||||||
|
<rect x="609" y="534" width="3" height="20" style="fill-opacity:0.3;fill:red"/>
|
||||||
|
<text x="604" y="549" style="text-anchor:end">+1.07%</text>
|
||||||
|
</g>
|
||||||
|
<text x="100" y="554" style="text-anchor:start">BenchmarkFilterFunction</text>
|
||||||
|
<g style="font-style:italic;font-size:75%">
|
||||||
|
<rect x="598" y="560" width="14" height="20" style="fill-opacity:0.3;fill:red"/>
|
||||||
|
<text x="593" y="575" style="text-anchor:end">+4.91%</text>
|
||||||
|
</g>
|
||||||
|
<text x="100" y="580" style="text-anchor:start">BenchmarkNotFunction</text>
|
||||||
|
<g style="font-style:italic;font-size:75%">
|
||||||
|
<rect x="609" y="586" width="3" height="20" style="fill-opacity:0.3;fill:red"/>
|
||||||
|
<text x="604" y="601" style="text-anchor:end">+1.03%</text>
|
||||||
|
</g>
|
||||||
|
<text x="100" y="606" style="text-anchor:start">BenchmarkFilterNodes</text>
|
||||||
|
<g style="font-style:italic;font-size:75%">
|
||||||
|
<rect x="600" y="612" width="12" height="20" style="fill-opacity:0.3;fill:red"/>
|
||||||
|
<text x="595" y="627" style="text-anchor:end">+4.22%</text>
|
||||||
|
</g>
|
||||||
|
<text x="100" y="632" style="text-anchor:start">BenchmarkNotNodes</text>
|
||||||
|
<g style="font-style:italic;font-size:75%">
|
||||||
|
<rect x="612" y="638" width="3" height="20" style="fill-opacity:0.3;fill:green"/>
|
||||||
|
<text x="620" y="653" style="text-anchor:start">-1.00%</text>
|
||||||
|
</g>
|
||||||
|
<text x="100" y="658" style="text-anchor:start">BenchmarkFilterSelection</text>
|
||||||
|
<g style="font-style:italic;font-size:75%">
|
||||||
|
<rect x="600" y="664" width="12" height="20" style="fill-opacity:0.3;fill:red"/>
|
||||||
|
<text x="595" y="679" style="text-anchor:end">+4.00%</text>
|
||||||
|
</g>
|
||||||
|
<text x="100" y="684" style="text-anchor:start">BenchmarkNotSelection</text>
|
||||||
|
<g style="font-style:italic;font-size:75%">
|
||||||
|
<rect x="612" y="690" width="96" height="20" style="fill-opacity:0.3;fill:green"/>
|
||||||
|
<text x="713" y="705" style="text-anchor:start">-32.12%</text>
|
||||||
|
</g>
|
||||||
|
<text x="100" y="710" style="text-anchor:start">BenchmarkHas</text>
|
||||||
|
<g style="font-style:italic;font-size:75%">
|
||||||
|
<rect x="608" y="716" width="4" height="20" style="fill-opacity:0.3;fill:red"/>
|
||||||
|
<text x="603" y="731" style="text-anchor:end">+1.59%</text>
|
||||||
|
</g>
|
||||||
|
<text x="100" y="736" style="text-anchor:start">BenchmarkHasNodes</text>
|
||||||
|
<g style="font-style:italic;font-size:75%">
|
||||||
|
<rect x="608" y="742" width="4" height="20" style="fill-opacity:0.3;fill:red"/>
|
||||||
|
<text x="603" y="757" style="text-anchor:end">+1.56%</text>
|
||||||
|
</g>
|
||||||
|
<text x="100" y="762" style="text-anchor:start">BenchmarkHasSelection</text>
|
||||||
|
<g style="font-style:italic;font-size:75%">
|
||||||
|
<rect x="566" y="768" width="46" height="20" style="fill-opacity:0.3;fill:red"/>
|
||||||
|
<text x="561" y="783" style="text-anchor:end">+15.54%</text>
|
||||||
|
</g>
|
||||||
|
<text x="100" y="788" style="text-anchor:start">BenchmarkEnd</text>
|
||||||
|
<g style="font-style:italic;font-size:75%">
|
||||||
|
<rect x="607" y="794" width="5" height="20" style="fill-opacity:0.3;fill:red"/>
|
||||||
|
<text x="602" y="809" style="text-anchor:end">+1.77%</text>
|
||||||
|
</g>
|
||||||
|
<text x="100" y="814" style="text-anchor:start">BenchmarkEach</text>
|
||||||
|
<g style="font-style:italic;font-size:75%">
|
||||||
|
<rect x="612" y="820" width="10" height="20" style="fill-opacity:0.3;fill:green"/>
|
||||||
|
<text x="627" y="835" style="text-anchor:start">-3.61%</text>
|
||||||
|
</g>
|
||||||
|
<text x="100" y="840" style="text-anchor:start">BenchmarkMap</text>
|
||||||
|
<g style="font-style:italic;font-size:75%">
|
||||||
|
<rect x="612" y="846" width="49" height="20" style="fill-opacity:0.3;fill:green"/>
|
||||||
|
<text x="666" y="861" style="text-anchor:start">-16.48%</text>
|
||||||
|
</g>
|
||||||
|
<text x="100" y="866" style="text-anchor:start">BenchmarkAttr</text>
|
||||||
|
<g style="font-style:italic;font-size:75%">
|
||||||
|
<rect x="609" y="872" width="3" height="20" style="fill-opacity:0.3;fill:red"/>
|
||||||
|
<text x="604" y="887" style="text-anchor:end">+1.33%</text>
|
||||||
|
</g>
|
||||||
|
<text x="100" y="892" style="text-anchor:start">BenchmarkText</text>
|
||||||
|
<g style="font-style:italic;font-size:75%">
|
||||||
|
<rect x="612" y="898" width="177" height="20" style="fill-opacity:0.3;fill:green"/>
|
||||||
|
<text x="794" y="913" style="text-anchor:start">-59.21%</text>
|
||||||
|
</g>
|
||||||
|
<text x="100" y="918" style="text-anchor:start">BenchmarkLength</text>
|
||||||
|
<g style="font-style:italic;font-size:75%">
|
||||||
|
<rect x="612" y="924" width="27" height="20" style="fill-opacity:0.3;fill:green"/>
|
||||||
|
<text x="644" y="939" style="text-anchor:start">-9.01%</text>
|
||||||
|
</g>
|
||||||
|
<text x="100" y="944" style="text-anchor:start">BenchmarkHtml</text>
|
||||||
|
<g style="font-style:italic;font-size:75%">
|
||||||
|
<rect x="612" y="950" width="50" height="20" style="fill-opacity:0.3;fill:green"/>
|
||||||
|
<text x="667" y="965" style="text-anchor:start">-16.73%</text>
|
||||||
|
</g>
|
||||||
|
<text x="100" y="970" style="text-anchor:start">BenchmarkIs</text>
|
||||||
|
<g style="font-style:italic;font-size:75%">
|
||||||
|
<rect x="612" y="976" width="75" height="20" style="fill-opacity:0.3;fill:green"/>
|
||||||
|
<text x="692" y="991" style="text-anchor:start">-25.08%</text>
|
||||||
|
</g>
|
||||||
|
<text x="100" y="996" style="text-anchor:start">BenchmarkIsPositional</text>
|
||||||
|
<g style="font-style:italic;font-size:75%">
|
||||||
|
<rect x="612" y="1002" width="34" height="20" style="fill-opacity:0.3;fill:green"/>
|
||||||
|
<text x="651" y="1017" style="text-anchor:start">-11.55%</text>
|
||||||
|
</g>
|
||||||
|
<text x="100" y="1022" style="text-anchor:start">BenchmarkIsFunction</text>
|
||||||
|
<g style="font-style:italic;font-size:75%">
|
||||||
|
<rect x="609" y="1028" width="3" height="20" style="fill-opacity:0.3;fill:red"/>
|
||||||
|
<text x="604" y="1043" style="text-anchor:end">+1.28%</text>
|
||||||
|
</g>
|
||||||
|
<text x="100" y="1048" style="text-anchor:start">BenchmarkIsSelection</text>
|
||||||
|
<g style="font-style:italic;font-size:75%">
|
||||||
|
<rect x="606" y="1054" width="6" height="20" style="fill-opacity:0.3;fill:red"/>
|
||||||
|
<text x="601" y="1069" style="text-anchor:end">+2.10%</text>
|
||||||
|
</g>
|
||||||
|
<text x="100" y="1074" style="text-anchor:start">BenchmarkIsNodes</text>
|
||||||
|
<g style="font-style:italic;font-size:75%">
|
||||||
|
<rect x="612" y="1080" width="47" height="20" style="fill-opacity:0.3;fill:green"/>
|
||||||
|
<text x="664" y="1095" style="text-anchor:start">-15.99%</text>
|
||||||
|
</g>
|
||||||
|
<text x="100" y="1100" style="text-anchor:start">BenchmarkHasClass</text>
|
||||||
|
<g style="font-style:italic;font-size:75%">
|
||||||
|
<rect x="612" y="1106" width="7" height="20" style="fill-opacity:0.3;fill:green"/>
|
||||||
|
<text x="624" y="1121" style="text-anchor:start">-2.65%</text>
|
||||||
|
</g>
|
||||||
|
<text x="100" y="1126" style="text-anchor:start">BenchmarkContains</text>
|
||||||
|
<g style="font-style:italic;font-size:75%">
|
||||||
|
<rect x="612" y="1132" width="145" height="20" style="fill-opacity:0.3;fill:green"/>
|
||||||
|
<text x="762" y="1147" style="text-anchor:start">-48.54%</text>
|
||||||
|
</g>
|
||||||
|
<text x="100" y="1152" style="text-anchor:start">BenchmarkFind</text>
|
||||||
|
<g style="font-style:italic;font-size:75%">
|
||||||
|
<rect x="612" y="1158" width="128" height="20" style="fill-opacity:0.3;fill:green"/>
|
||||||
|
<text x="745" y="1173" style="text-anchor:start">-42.71%</text>
|
||||||
|
</g>
|
||||||
|
<text x="100" y="1178" style="text-anchor:start">BenchmarkFindWithinSelection</text>
|
||||||
|
<g style="font-style:italic;font-size:75%">
|
||||||
|
<rect x="526" y="1184" width="86" height="20" style="fill-opacity:0.3;fill:red"/>
|
||||||
|
<text x="521" y="1199" style="text-anchor:end">+28.77%</text>
|
||||||
|
</g>
|
||||||
|
<text x="100" y="1204" style="text-anchor:start">BenchmarkFindSelection</text>
|
||||||
|
<g style="font-style:italic;font-size:75%">
|
||||||
|
<rect x="527" y="1210" width="85" height="20" style="fill-opacity:0.3;fill:red"/>
|
||||||
|
<text x="522" y="1225" style="text-anchor:end">+28.47%</text>
|
||||||
|
</g>
|
||||||
|
<text x="100" y="1230" style="text-anchor:start">BenchmarkFindNodes</text>
|
||||||
|
<g style="font-style:italic;font-size:75%">
|
||||||
|
<rect x="612" y="1236" width="188" height="20" style="fill-opacity:0.3;fill:green"/>
|
||||||
|
<text x="805" y="1251" style="text-anchor:start">-62.84%</text>
|
||||||
|
</g>
|
||||||
|
<text x="100" y="1256" style="text-anchor:start">BenchmarkContents</text>
|
||||||
|
<g style="font-style:italic;font-size:75%">
|
||||||
|
<rect x="612" y="1262" width="174" height="20" style="fill-opacity:0.3;fill:green"/>
|
||||||
|
<text x="791" y="1277" style="text-anchor:start">-58.06%</text>
|
||||||
|
</g>
|
||||||
|
<text x="100" y="1282" style="text-anchor:start">BenchmarkContentsFiltered</text>
|
||||||
|
<g style="font-style:italic;font-size:75%">
|
||||||
|
<rect x="612" y="1288" width="189" height="20" style="fill-opacity:0.3;fill:green"/>
|
||||||
|
<text x="806" y="1303" style="text-anchor:start">-63.13%</text>
|
||||||
|
</g>
|
||||||
|
<text x="100" y="1308" style="text-anchor:start">BenchmarkChildren</text>
|
||||||
|
<g style="font-style:italic;font-size:75%">
|
||||||
|
<rect x="612" y="1314" width="114" height="20" style="fill-opacity:0.3;fill:green"/>
|
||||||
|
<text x="731" y="1329" style="text-anchor:start">-38.24%</text>
|
||||||
|
</g>
|
||||||
|
<text x="100" y="1334" style="text-anchor:start">BenchmarkChildrenFiltered</text>
|
||||||
|
<g style="font-style:italic;font-size:75%">
|
||||||
|
<rect x="612" y="1340" width="10" height="20" style="fill-opacity:0.3;fill:green"/>
|
||||||
|
<text x="627" y="1355" style="text-anchor:start">-3.66%</text>
|
||||||
|
</g>
|
||||||
|
<text x="100" y="1360" style="text-anchor:start">BenchmarkParent</text>
|
||||||
|
<g style="font-style:italic;font-size:75%">
|
||||||
|
<rect x="612" y="1366" width="18" height="20" style="fill-opacity:0.3;fill:green"/>
|
||||||
|
<text x="635" y="1381" style="text-anchor:start">-6.06%</text>
|
||||||
|
</g>
|
||||||
|
<text x="100" y="1386" style="text-anchor:start">BenchmarkParentFiltered</text>
|
||||||
|
<g style="font-style:italic;font-size:75%">
|
||||||
|
<rect x="602" y="1392" width="10" height="20" style="fill-opacity:0.3;fill:red"/>
|
||||||
|
<text x="597" y="1407" style="text-anchor:end">+3.64%</text>
|
||||||
|
</g>
|
||||||
|
<text x="100" y="1412" style="text-anchor:start">BenchmarkParents</text>
|
||||||
|
<g style="font-style:italic;font-size:75%">
|
||||||
|
<rect x="608" y="1418" width="4" height="20" style="fill-opacity:0.3;fill:red"/>
|
||||||
|
<text x="603" y="1433" style="text-anchor:end">+1.44%</text>
|
||||||
|
</g>
|
||||||
|
<text x="100" y="1438" style="text-anchor:start">BenchmarkParentsFiltered</text>
|
||||||
|
<g style="font-style:italic;font-size:75%">
|
||||||
|
<rect x="612" y="1444" width="133" height="20" style="fill-opacity:0.3;fill:green"/>
|
||||||
|
<text x="750" y="1459" style="text-anchor:start">-44.35%</text>
|
||||||
|
</g>
|
||||||
|
<text x="100" y="1464" style="text-anchor:start">BenchmarkParentsUntil</text>
|
||||||
|
<g style="font-style:italic;font-size:75%">
|
||||||
|
<rect x="612" y="1470" width="95" height="20" style="fill-opacity:0.3;fill:green"/>
|
||||||
|
<text x="712" y="1485" style="text-anchor:start">-31.99%</text>
|
||||||
|
</g>
|
||||||
|
<text x="100" y="1490" style="text-anchor:start">BenchmarkParentsUntilSelection</text>
|
||||||
|
<g style="font-style:italic;font-size:75%">
|
||||||
|
<rect x="612" y="1496" width="97" height="20" style="fill-opacity:0.3;fill:green"/>
|
||||||
|
<text x="714" y="1511" style="text-anchor:start">-32.62%</text>
|
||||||
|
</g>
|
||||||
|
<text x="100" y="1516" style="text-anchor:start">BenchmarkParentsUntilNodes</text>
|
||||||
|
<g style="font-style:italic;font-size:75%">
|
||||||
|
<rect x="612" y="1522" width="137" height="20" style="fill-opacity:0.3;fill:green"/>
|
||||||
|
<text x="754" y="1537" style="text-anchor:start">-45.83%</text>
|
||||||
|
</g>
|
||||||
|
<text x="100" y="1542" style="text-anchor:start">BenchmarkParentsFilteredUntil</text>
|
||||||
|
<g style="font-style:italic;font-size:75%">
|
||||||
|
<rect x="612" y="1548" width="90" height="20" style="fill-opacity:0.3;fill:green"/>
|
||||||
|
<text x="707" y="1563" style="text-anchor:start">-30.05%</text>
|
||||||
|
</g>
|
||||||
|
<text x="100" y="1568" style="text-anchor:start">BenchmarkParentsFilteredUntilSelection</text>
|
||||||
|
<g style="font-style:italic;font-size:75%">
|
||||||
|
<rect x="612" y="1574" width="89" height="20" style="fill-opacity:0.3;fill:green"/>
|
||||||
|
<text x="706" y="1589" style="text-anchor:start">-29.97%</text>
|
||||||
|
</g>
|
||||||
|
<text x="100" y="1594" style="text-anchor:start">BenchmarkParentsFilteredUntilNodes</text>
|
||||||
|
<g style="font-style:italic;font-size:75%">
|
||||||
|
<rect x="612" y="1600" width="77" height="20" style="fill-opacity:0.3;fill:green"/>
|
||||||
|
<text x="694" y="1615" style="text-anchor:start">-25.96%</text>
|
||||||
|
</g>
|
||||||
|
<text x="100" y="1620" style="text-anchor:start">BenchmarkSiblings</text>
|
||||||
|
<g style="font-style:italic;font-size:75%">
|
||||||
|
<rect x="612" y="1626" width="80" height="20" style="fill-opacity:0.3;fill:green"/>
|
||||||
|
<text x="697" y="1641" style="text-anchor:start">-26.67%</text>
|
||||||
|
</g>
|
||||||
|
<text x="100" y="1646" style="text-anchor:start">BenchmarkSiblingsFiltered</text>
|
||||||
|
<g style="font-style:italic;font-size:75%">
|
||||||
|
<rect x="612" y="1652" width="199" height="20" style="fill-opacity:0.3;fill:green"/>
|
||||||
|
<text x="816" y="1667" style="text-anchor:start">-66.40%</text>
|
||||||
|
</g>
|
||||||
|
<text x="100" y="1672" style="text-anchor:start">BenchmarkNext</text>
|
||||||
|
<g style="font-style:italic;font-size:75%">
|
||||||
|
<rect x="612" y="1678" width="193" height="20" style="fill-opacity:0.3;fill:green"/>
|
||||||
|
<text x="810" y="1693" style="text-anchor:start">-64.46%</text>
|
||||||
|
</g>
|
||||||
|
<text x="100" y="1698" style="text-anchor:start">BenchmarkNextFiltered</text>
|
||||||
|
<g style="font-style:italic;font-size:75%">
|
||||||
|
<rect x="612" y="1704" width="79" height="20" style="fill-opacity:0.3;fill:green"/>
|
||||||
|
<text x="696" y="1719" style="text-anchor:start">-26.50%</text>
|
||||||
|
</g>
|
||||||
|
<text x="100" y="1724" style="text-anchor:start">BenchmarkNextAll</text>
|
||||||
|
<g style="font-style:italic;font-size:75%">
|
||||||
|
<rect x="612" y="1730" width="78" height="20" style="fill-opacity:0.3;fill:green"/>
|
||||||
|
<text x="695" y="1745" style="text-anchor:start">-26.27%</text>
|
||||||
|
</g>
|
||||||
|
<text x="100" y="1750" style="text-anchor:start">BenchmarkNextAllFiltered</text>
|
||||||
|
<g style="font-style:italic;font-size:75%">
|
||||||
|
<rect x="612" y="1756" width="200" height="20" style="fill-opacity:0.3;fill:green"/>
|
||||||
|
<text x="817" y="1771" style="text-anchor:start">-66.84%</text>
|
||||||
|
</g>
|
||||||
|
<text x="100" y="1776" style="text-anchor:start">BenchmarkPrev</text>
|
||||||
|
<g style="font-style:italic;font-size:75%">
|
||||||
|
<rect x="612" y="1782" width="193" height="20" style="fill-opacity:0.3;fill:green"/>
|
||||||
|
<text x="810" y="1797" style="text-anchor:start">-64.35%</text>
|
||||||
|
</g>
|
||||||
|
<text x="100" y="1802" style="text-anchor:start">BenchmarkPrevFiltered</text>
|
||||||
|
<g style="font-style:italic;font-size:75%">
|
||||||
|
<rect x="612" y="1808" width="120" height="20" style="fill-opacity:0.3;fill:green"/>
|
||||||
|
<text x="737" y="1823" style="text-anchor:start">-40.05%</text>
|
||||||
|
</g>
|
||||||
|
<text x="100" y="1828" style="text-anchor:start">BenchmarkPrevAll</text>
|
||||||
|
<g style="font-style:italic;font-size:75%">
|
||||||
|
<rect x="612" y="1834" width="119" height="20" style="fill-opacity:0.3;fill:green"/>
|
||||||
|
<text x="736" y="1849" style="text-anchor:start">-39.74%</text>
|
||||||
|
</g>
|
||||||
|
<text x="100" y="1854" style="text-anchor:start">BenchmarkPrevAllFiltered</text>
|
||||||
|
<g style="font-style:italic;font-size:75%">
|
||||||
|
<rect x="612" y="1860" width="155" height="20" style="fill-opacity:0.3;fill:green"/>
|
||||||
|
<text x="772" y="1875" style="text-anchor:start">-51.73%</text>
|
||||||
|
</g>
|
||||||
|
<text x="100" y="1880" style="text-anchor:start">BenchmarkNextUntil</text>
|
||||||
|
<g style="font-style:italic;font-size:75%">
|
||||||
|
<rect x="612" y="1886" width="100" height="20" style="fill-opacity:0.3;fill:green"/>
|
||||||
|
<text x="717" y="1901" style="text-anchor:start">-33.42%</text>
|
||||||
|
</g>
|
||||||
|
<text x="100" y="1906" style="text-anchor:start">BenchmarkNextUntilSelection</text>
|
||||||
|
<g style="font-style:italic;font-size:75%">
|
||||||
|
<rect x="612" y="1912" width="121" height="20" style="fill-opacity:0.3;fill:green"/>
|
||||||
|
<text x="738" y="1927" style="text-anchor:start">-40.42%</text>
|
||||||
|
</g>
|
||||||
|
<text x="100" y="1932" style="text-anchor:start">BenchmarkNextUntilNodes</text>
|
||||||
|
<g style="font-style:italic;font-size:75%">
|
||||||
|
<rect x="612" y="1938" width="140" height="20" style="fill-opacity:0.3;fill:green"/>
|
||||||
|
<text x="757" y="1953" style="text-anchor:start">-46.87%</text>
|
||||||
|
</g>
|
||||||
|
<text x="100" y="1958" style="text-anchor:start">BenchmarkPrevUntil</text>
|
||||||
|
<g style="font-style:italic;font-size:75%">
|
||||||
|
<rect x="612" y="1964" width="99" height="20" style="fill-opacity:0.3;fill:green"/>
|
||||||
|
<text x="716" y="1979" style="text-anchor:start">-33.14%</text>
|
||||||
|
</g>
|
||||||
|
<text x="100" y="1984" style="text-anchor:start">BenchmarkPrevUntilSelection</text>
|
||||||
|
<g style="font-style:italic;font-size:75%">
|
||||||
|
<rect x="612" y="1990" width="123" height="20" style="fill-opacity:0.3;fill:green"/>
|
||||||
|
<text x="740" y="2005" style="text-anchor:start">-41.19%</text>
|
||||||
|
</g>
|
||||||
|
<text x="100" y="2010" style="text-anchor:start">BenchmarkPrevUntilNodes</text>
|
||||||
|
<g style="font-style:italic;font-size:75%">
|
||||||
|
<rect x="612" y="2016" width="167" height="20" style="fill-opacity:0.3;fill:green"/>
|
||||||
|
<text x="784" y="2031" style="text-anchor:start">-55.92%</text>
|
||||||
|
</g>
|
||||||
|
<text x="100" y="2036" style="text-anchor:start">BenchmarkNextFilteredUntil</text>
|
||||||
|
<g style="font-style:italic;font-size:75%">
|
||||||
|
<rect x="612" y="2042" width="97" height="20" style="fill-opacity:0.3;fill:green"/>
|
||||||
|
<text x="714" y="2057" style="text-anchor:start">-32.49%</text>
|
||||||
|
</g>
|
||||||
|
<text x="100" y="2062" style="text-anchor:start">BenchmarkNextFilteredUntilSelection</text>
|
||||||
|
<g style="font-style:italic;font-size:75%">
|
||||||
|
<rect x="612" y="2068" width="99" height="20" style="fill-opacity:0.3;fill:green"/>
|
||||||
|
<text x="716" y="2083" style="text-anchor:start">-33.00%</text>
|
||||||
|
</g>
|
||||||
|
<text x="100" y="2088" style="text-anchor:start">BenchmarkNextFilteredUntilNodes</text>
|
||||||
|
<g style="font-style:italic;font-size:75%">
|
||||||
|
<rect x="612" y="2094" width="175" height="20" style="fill-opacity:0.3;fill:green"/>
|
||||||
|
<text x="792" y="2109" style="text-anchor:start">-58.54%</text>
|
||||||
|
</g>
|
||||||
|
<text x="100" y="2114" style="text-anchor:start">BenchmarkPrevFilteredUntil</text>
|
||||||
|
<g style="font-style:italic;font-size:75%">
|
||||||
|
<rect x="612" y="2120" width="101" height="20" style="fill-opacity:0.3;fill:green"/>
|
||||||
|
<text x="718" y="2135" style="text-anchor:start">-33.80%</text>
|
||||||
|
</g>
|
||||||
|
<text x="100" y="2140" style="text-anchor:start">BenchmarkPrevFilteredUntilSelection</text>
|
||||||
|
<g style="font-style:italic;font-size:75%">
|
||||||
|
<rect x="612" y="2146" width="100" height="20" style="fill-opacity:0.3;fill:green"/>
|
||||||
|
<text x="717" y="2161" style="text-anchor:start">-33.44%</text>
|
||||||
|
</g>
|
||||||
|
<text x="100" y="2166" style="text-anchor:start">BenchmarkPrevFilteredUntilNodes</text>
|
||||||
|
<g style="font-style:italic;font-size:75%">
|
||||||
|
<rect x="612" y="2172" width="74" height="20" style="fill-opacity:0.3;fill:green"/>
|
||||||
|
<text x="691" y="2187" style="text-anchor:start">-24.82%</text>
|
||||||
|
</g>
|
||||||
|
<text x="100" y="2192" style="text-anchor:start">BenchmarkClosest</text>
|
||||||
|
<g style="font-style:italic;font-size:75%">
|
||||||
|
<rect x="612" y="2198" width="103" height="20" style="fill-opacity:0.3;fill:green"/>
|
||||||
|
<text x="720" y="2213" style="text-anchor:start">-34.45%</text>
|
||||||
|
</g>
|
||||||
|
<text x="100" y="2218" style="text-anchor:start">BenchmarkClosestSelection</text>
|
||||||
|
<g style="font-style:italic;font-size:75%">
|
||||||
|
<rect x="612" y="2224" width="105" height="20" style="fill-opacity:0.3;fill:green"/>
|
||||||
|
<text x="722" y="2239" style="text-anchor:start">-35.30%</text>
|
||||||
|
</g>
|
||||||
|
<text x="100" y="2244" style="text-anchor:start">BenchmarkClosestNodes</text>
|
||||||
|
</g>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 22 KiB |
470
Godeps/_workspace/src/github.com/PuerkitoBio/goquery/bench/v0.2.1-go1.1rc1
generated
vendored
Normal file
470
Godeps/_workspace/src/github.com/PuerkitoBio/goquery/bench/v0.2.1-go1.1rc1
generated
vendored
Normal file
|
@ -0,0 +1,470 @@
|
||||||
|
PASS
|
||||||
|
BenchmarkFirst 20000000 96.3 ns/op
|
||||||
|
BenchmarkLast 20000000 95.7 ns/op
|
||||||
|
BenchmarkEq 20000000 97.1 ns/op
|
||||||
|
BenchmarkSlice 20000000 92.3 ns/op
|
||||||
|
BenchmarkGet 1000000000 2.06 ns/op
|
||||||
|
BenchmarkIndex 1000000 1069 ns/op
|
||||||
|
--- BENCH: BenchmarkIndex
|
||||||
|
bench_array_test.go:73: Index=3
|
||||||
|
bench_array_test.go:73: Index=3
|
||||||
|
bench_array_test.go:73: Index=3
|
||||||
|
bench_array_test.go:73: Index=3
|
||||||
|
BenchmarkIndexSelector 100000 26750 ns/op
|
||||||
|
--- BENCH: BenchmarkIndexSelector
|
||||||
|
bench_array_test.go:85: IndexSelector=4
|
||||||
|
bench_array_test.go:85: IndexSelector=4
|
||||||
|
bench_array_test.go:85: IndexSelector=4
|
||||||
|
bench_array_test.go:85: IndexSelector=4
|
||||||
|
BenchmarkIndexOfNode 100000000 10.7 ns/op
|
||||||
|
--- BENCH: BenchmarkIndexOfNode
|
||||||
|
bench_array_test.go:99: IndexOfNode=2
|
||||||
|
bench_array_test.go:99: IndexOfNode=2
|
||||||
|
bench_array_test.go:99: IndexOfNode=2
|
||||||
|
bench_array_test.go:99: IndexOfNode=2
|
||||||
|
bench_array_test.go:99: IndexOfNode=2
|
||||||
|
BenchmarkIndexOfSelection 100000000 11.8 ns/op
|
||||||
|
--- BENCH: BenchmarkIndexOfSelection
|
||||||
|
bench_array_test.go:111: IndexOfSelection=2
|
||||||
|
bench_array_test.go:111: IndexOfSelection=2
|
||||||
|
bench_array_test.go:111: IndexOfSelection=2
|
||||||
|
bench_array_test.go:111: IndexOfSelection=2
|
||||||
|
bench_array_test.go:111: IndexOfSelection=2
|
||||||
|
BenchmarkMetalReviewExample 10000 219078 ns/op
|
||||||
|
--- BENCH: BenchmarkMetalReviewExample
|
||||||
|
bench_example_test.go:40: Review 0: Midnight - Complete and Total Hell (8.5).
|
||||||
|
Review 1: Over Your Threshold - Facticity (6.0).
|
||||||
|
Review 2: Nuclear Death Terror - Chaos Reigns (7.5).
|
||||||
|
Review 3: Evoken - Atra Mors (9.5).
|
||||||
|
|
||||||
|
bench_example_test.go:41: MetalReviewExample=10
|
||||||
|
bench_example_test.go:40: Review 0: Midnight - Complete and Total Hell (8.5).
|
||||||
|
Review 1: Over Your Threshold - Facticity (6.0).
|
||||||
|
Review 2: Nuclear Death Terror - Chaos Reigns (7.5).
|
||||||
|
Review 3: Evoken - Atra Mors (9.5).
|
||||||
|
... [output truncated]
|
||||||
|
BenchmarkAdd 100000 22345 ns/op
|
||||||
|
--- BENCH: BenchmarkAdd
|
||||||
|
bench_expand_test.go:20: Add=43
|
||||||
|
bench_expand_test.go:20: Add=43
|
||||||
|
bench_expand_test.go:20: Add=43
|
||||||
|
bench_expand_test.go:20: Add=43
|
||||||
|
BenchmarkAddSelection 10000000 209 ns/op
|
||||||
|
--- BENCH: BenchmarkAddSelection
|
||||||
|
bench_expand_test.go:37: AddSelection=43
|
||||||
|
bench_expand_test.go:37: AddSelection=43
|
||||||
|
bench_expand_test.go:37: AddSelection=43
|
||||||
|
bench_expand_test.go:37: AddSelection=43
|
||||||
|
bench_expand_test.go:37: AddSelection=43
|
||||||
|
BenchmarkAddNodes 10000000 209 ns/op
|
||||||
|
--- BENCH: BenchmarkAddNodes
|
||||||
|
bench_expand_test.go:55: AddNodes=43
|
||||||
|
bench_expand_test.go:55: AddNodes=43
|
||||||
|
bench_expand_test.go:55: AddNodes=43
|
||||||
|
bench_expand_test.go:55: AddNodes=43
|
||||||
|
bench_expand_test.go:55: AddNodes=43
|
||||||
|
BenchmarkAndSelf 1000000 2568 ns/op
|
||||||
|
--- BENCH: BenchmarkAndSelf
|
||||||
|
bench_expand_test.go:71: AndSelf=44
|
||||||
|
bench_expand_test.go:71: AndSelf=44
|
||||||
|
bench_expand_test.go:71: AndSelf=44
|
||||||
|
bench_expand_test.go:71: AndSelf=44
|
||||||
|
BenchmarkFilter 100000 26715 ns/op
|
||||||
|
--- BENCH: BenchmarkFilter
|
||||||
|
bench_filter_test.go:20: Filter=13
|
||||||
|
bench_filter_test.go:20: Filter=13
|
||||||
|
bench_filter_test.go:20: Filter=13
|
||||||
|
bench_filter_test.go:20: Filter=13
|
||||||
|
BenchmarkNot 50000 30058 ns/op
|
||||||
|
--- BENCH: BenchmarkNot
|
||||||
|
bench_filter_test.go:36: Not=371
|
||||||
|
bench_filter_test.go:36: Not=371
|
||||||
|
bench_filter_test.go:36: Not=371
|
||||||
|
bench_filter_test.go:36: Not=371
|
||||||
|
BenchmarkFilterFunction 50000 66346 ns/op
|
||||||
|
--- BENCH: BenchmarkFilterFunction
|
||||||
|
bench_filter_test.go:55: FilterFunction=112
|
||||||
|
bench_filter_test.go:55: FilterFunction=112
|
||||||
|
bench_filter_test.go:55: FilterFunction=112
|
||||||
|
bench_filter_test.go:55: FilterFunction=112
|
||||||
|
BenchmarkNotFunction 50000 72646 ns/op
|
||||||
|
--- BENCH: BenchmarkNotFunction
|
||||||
|
bench_filter_test.go:74: NotFunction=261
|
||||||
|
bench_filter_test.go:74: NotFunction=261
|
||||||
|
bench_filter_test.go:74: NotFunction=261
|
||||||
|
bench_filter_test.go:74: NotFunction=261
|
||||||
|
BenchmarkFilterNodes 50000 65493 ns/op
|
||||||
|
--- BENCH: BenchmarkFilterNodes
|
||||||
|
bench_filter_test.go:92: FilterNodes=2
|
||||||
|
bench_filter_test.go:92: FilterNodes=2
|
||||||
|
bench_filter_test.go:92: FilterNodes=2
|
||||||
|
bench_filter_test.go:92: FilterNodes=2
|
||||||
|
BenchmarkNotNodes 20000 79466 ns/op
|
||||||
|
--- BENCH: BenchmarkNotNodes
|
||||||
|
bench_filter_test.go:110: NotNodes=360
|
||||||
|
bench_filter_test.go:110: NotNodes=360
|
||||||
|
bench_filter_test.go:110: NotNodes=360
|
||||||
|
bench_filter_test.go:110: NotNodes=360
|
||||||
|
BenchmarkFilterSelection 50000 65494 ns/op
|
||||||
|
--- BENCH: BenchmarkFilterSelection
|
||||||
|
bench_filter_test.go:127: FilterSelection=2
|
||||||
|
bench_filter_test.go:127: FilterSelection=2
|
||||||
|
bench_filter_test.go:127: FilterSelection=2
|
||||||
|
bench_filter_test.go:127: FilterSelection=2
|
||||||
|
BenchmarkNotSelection 20000 79387 ns/op
|
||||||
|
--- BENCH: BenchmarkNotSelection
|
||||||
|
bench_filter_test.go:144: NotSelection=360
|
||||||
|
bench_filter_test.go:144: NotSelection=360
|
||||||
|
bench_filter_test.go:144: NotSelection=360
|
||||||
|
bench_filter_test.go:144: NotSelection=360
|
||||||
|
BenchmarkHas 5000 386571 ns/op
|
||||||
|
--- BENCH: BenchmarkHas
|
||||||
|
bench_filter_test.go:160: Has=13
|
||||||
|
bench_filter_test.go:160: Has=13
|
||||||
|
bench_filter_test.go:160: Has=13
|
||||||
|
BenchmarkHasNodes 10000 230664 ns/op
|
||||||
|
--- BENCH: BenchmarkHasNodes
|
||||||
|
bench_filter_test.go:178: HasNodes=15
|
||||||
|
bench_filter_test.go:178: HasNodes=15
|
||||||
|
bench_filter_test.go:178: HasNodes=15
|
||||||
|
BenchmarkHasSelection 10000 230705 ns/op
|
||||||
|
--- BENCH: BenchmarkHasSelection
|
||||||
|
bench_filter_test.go:195: HasSelection=15
|
||||||
|
bench_filter_test.go:195: HasSelection=15
|
||||||
|
bench_filter_test.go:195: HasSelection=15
|
||||||
|
BenchmarkEnd 500000000 4.61 ns/op
|
||||||
|
--- BENCH: BenchmarkEnd
|
||||||
|
bench_filter_test.go:211: End=373
|
||||||
|
bench_filter_test.go:211: End=373
|
||||||
|
bench_filter_test.go:211: End=373
|
||||||
|
bench_filter_test.go:211: End=373
|
||||||
|
bench_filter_test.go:211: End=373
|
||||||
|
bench_filter_test.go:211: End=373
|
||||||
|
BenchmarkEach 200000 9520 ns/op
|
||||||
|
--- BENCH: BenchmarkEach
|
||||||
|
bench_iteration_test.go:22: Each=59
|
||||||
|
bench_iteration_test.go:22: Each=59
|
||||||
|
bench_iteration_test.go:22: Each=59
|
||||||
|
bench_iteration_test.go:22: Each=59
|
||||||
|
BenchmarkMap 100000 15960 ns/op
|
||||||
|
--- BENCH: BenchmarkMap
|
||||||
|
bench_iteration_test.go:41: Map=59
|
||||||
|
bench_iteration_test.go:41: Map=59
|
||||||
|
bench_iteration_test.go:41: Map=59
|
||||||
|
bench_iteration_test.go:41: Map=59
|
||||||
|
BenchmarkAttr 50000000 30.4 ns/op
|
||||||
|
--- BENCH: BenchmarkAttr
|
||||||
|
bench_property_test.go:16: Attr=firstHeading
|
||||||
|
bench_property_test.go:16: Attr=firstHeading
|
||||||
|
bench_property_test.go:16: Attr=firstHeading
|
||||||
|
bench_property_test.go:16: Attr=firstHeading
|
||||||
|
bench_property_test.go:16: Attr=firstHeading
|
||||||
|
BenchmarkText 100000 18718 ns/op
|
||||||
|
BenchmarkLength 2000000000 0.31 ns/op
|
||||||
|
--- BENCH: BenchmarkLength
|
||||||
|
bench_property_test.go:37: Length=14
|
||||||
|
bench_property_test.go:37: Length=14
|
||||||
|
bench_property_test.go:37: Length=14
|
||||||
|
bench_property_test.go:37: Length=14
|
||||||
|
bench_property_test.go:37: Length=14
|
||||||
|
bench_property_test.go:37: Length=14
|
||||||
|
BenchmarkHtml 5000000 606 ns/op
|
||||||
|
BenchmarkIs 100000 29289 ns/op
|
||||||
|
--- BENCH: BenchmarkIs
|
||||||
|
bench_query_test.go:16: Is=true
|
||||||
|
bench_query_test.go:16: Is=true
|
||||||
|
bench_query_test.go:16: Is=true
|
||||||
|
bench_query_test.go:16: Is=true
|
||||||
|
BenchmarkIsPositional 100000 23834 ns/op
|
||||||
|
--- BENCH: BenchmarkIsPositional
|
||||||
|
bench_query_test.go:28: IsPositional=true
|
||||||
|
bench_query_test.go:28: IsPositional=true
|
||||||
|
bench_query_test.go:28: IsPositional=true
|
||||||
|
bench_query_test.go:28: IsPositional=true
|
||||||
|
BenchmarkIsFunction 1000000 2436 ns/op
|
||||||
|
--- BENCH: BenchmarkIsFunction
|
||||||
|
bench_query_test.go:43: IsFunction=true
|
||||||
|
bench_query_test.go:43: IsFunction=true
|
||||||
|
bench_query_test.go:43: IsFunction=true
|
||||||
|
bench_query_test.go:43: IsFunction=true
|
||||||
|
BenchmarkIsSelection 50000 67106 ns/op
|
||||||
|
--- BENCH: BenchmarkIsSelection
|
||||||
|
bench_query_test.go:56: IsSelection=true
|
||||||
|
bench_query_test.go:56: IsSelection=true
|
||||||
|
bench_query_test.go:56: IsSelection=true
|
||||||
|
bench_query_test.go:56: IsSelection=true
|
||||||
|
BenchmarkIsNodes 50000 66042 ns/op
|
||||||
|
--- BENCH: BenchmarkIsNodes
|
||||||
|
bench_query_test.go:70: IsNodes=true
|
||||||
|
bench_query_test.go:70: IsNodes=true
|
||||||
|
bench_query_test.go:70: IsNodes=true
|
||||||
|
bench_query_test.go:70: IsNodes=true
|
||||||
|
BenchmarkHasClass 5000 565347 ns/op
|
||||||
|
--- BENCH: BenchmarkHasClass
|
||||||
|
bench_query_test.go:82: HasClass=true
|
||||||
|
bench_query_test.go:82: HasClass=true
|
||||||
|
bench_query_test.go:82: HasClass=true
|
||||||
|
BenchmarkContains 100000000 11.0 ns/op
|
||||||
|
--- BENCH: BenchmarkContains
|
||||||
|
bench_query_test.go:96: Contains=true
|
||||||
|
bench_query_test.go:96: Contains=true
|
||||||
|
bench_query_test.go:96: Contains=true
|
||||||
|
bench_query_test.go:96: Contains=true
|
||||||
|
bench_query_test.go:96: Contains=true
|
||||||
|
BenchmarkFind 100000 27677 ns/op
|
||||||
|
--- BENCH: BenchmarkFind
|
||||||
|
bench_traversal_test.go:18: Find=41
|
||||||
|
bench_traversal_test.go:18: Find=41
|
||||||
|
bench_traversal_test.go:18: Find=41
|
||||||
|
bench_traversal_test.go:18: Find=41
|
||||||
|
BenchmarkFindWithinSelection 50000 72162 ns/op
|
||||||
|
--- BENCH: BenchmarkFindWithinSelection
|
||||||
|
bench_traversal_test.go:34: FindWithinSelection=39
|
||||||
|
bench_traversal_test.go:34: FindWithinSelection=39
|
||||||
|
bench_traversal_test.go:34: FindWithinSelection=39
|
||||||
|
bench_traversal_test.go:34: FindWithinSelection=39
|
||||||
|
BenchmarkFindSelection 5000 460124 ns/op
|
||||||
|
--- BENCH: BenchmarkFindSelection
|
||||||
|
bench_traversal_test.go:51: FindSelection=73
|
||||||
|
bench_traversal_test.go:51: FindSelection=73
|
||||||
|
bench_traversal_test.go:51: FindSelection=73
|
||||||
|
BenchmarkFindNodes 5000 459390 ns/op
|
||||||
|
--- BENCH: BenchmarkFindNodes
|
||||||
|
bench_traversal_test.go:69: FindNodes=73
|
||||||
|
bench_traversal_test.go:69: FindNodes=73
|
||||||
|
bench_traversal_test.go:69: FindNodes=73
|
||||||
|
BenchmarkContents 500000 3395 ns/op
|
||||||
|
--- BENCH: BenchmarkContents
|
||||||
|
bench_traversal_test.go:85: Contents=16
|
||||||
|
bench_traversal_test.go:85: Contents=16
|
||||||
|
bench_traversal_test.go:85: Contents=16
|
||||||
|
bench_traversal_test.go:85: Contents=16
|
||||||
|
BenchmarkContentsFiltered 500000 5193 ns/op
|
||||||
|
--- BENCH: BenchmarkContentsFiltered
|
||||||
|
bench_traversal_test.go:101: ContentsFiltered=1
|
||||||
|
bench_traversal_test.go:101: ContentsFiltered=1
|
||||||
|
bench_traversal_test.go:101: ContentsFiltered=1
|
||||||
|
bench_traversal_test.go:101: ContentsFiltered=1
|
||||||
|
BenchmarkChildren 5000000 667 ns/op
|
||||||
|
--- BENCH: BenchmarkChildren
|
||||||
|
bench_traversal_test.go:117: Children=2
|
||||||
|
bench_traversal_test.go:117: Children=2
|
||||||
|
bench_traversal_test.go:117: Children=2
|
||||||
|
bench_traversal_test.go:117: Children=2
|
||||||
|
bench_traversal_test.go:117: Children=2
|
||||||
|
BenchmarkChildrenFiltered 500000 3591 ns/op
|
||||||
|
--- BENCH: BenchmarkChildrenFiltered
|
||||||
|
bench_traversal_test.go:133: ChildrenFiltered=2
|
||||||
|
bench_traversal_test.go:133: ChildrenFiltered=2
|
||||||
|
bench_traversal_test.go:133: ChildrenFiltered=2
|
||||||
|
bench_traversal_test.go:133: ChildrenFiltered=2
|
||||||
|
BenchmarkParent 50000 43168 ns/op
|
||||||
|
--- BENCH: BenchmarkParent
|
||||||
|
bench_traversal_test.go:149: Parent=55
|
||||||
|
bench_traversal_test.go:149: Parent=55
|
||||||
|
bench_traversal_test.go:149: Parent=55
|
||||||
|
bench_traversal_test.go:149: Parent=55
|
||||||
|
BenchmarkParentFiltered 50000 45836 ns/op
|
||||||
|
--- BENCH: BenchmarkParentFiltered
|
||||||
|
bench_traversal_test.go:165: ParentFiltered=4
|
||||||
|
bench_traversal_test.go:165: ParentFiltered=4
|
||||||
|
bench_traversal_test.go:165: ParentFiltered=4
|
||||||
|
bench_traversal_test.go:165: ParentFiltered=4
|
||||||
|
BenchmarkParents 20000 92348 ns/op
|
||||||
|
--- BENCH: BenchmarkParents
|
||||||
|
bench_traversal_test.go:181: Parents=73
|
||||||
|
bench_traversal_test.go:181: Parents=73
|
||||||
|
bench_traversal_test.go:181: Parents=73
|
||||||
|
bench_traversal_test.go:181: Parents=73
|
||||||
|
BenchmarkParentsFiltered 20000 95306 ns/op
|
||||||
|
--- BENCH: BenchmarkParentsFiltered
|
||||||
|
bench_traversal_test.go:197: ParentsFiltered=18
|
||||||
|
bench_traversal_test.go:197: ParentsFiltered=18
|
||||||
|
bench_traversal_test.go:197: ParentsFiltered=18
|
||||||
|
bench_traversal_test.go:197: ParentsFiltered=18
|
||||||
|
BenchmarkParentsUntil 50000 72782 ns/op
|
||||||
|
--- BENCH: BenchmarkParentsUntil
|
||||||
|
bench_traversal_test.go:213: ParentsUntil=52
|
||||||
|
bench_traversal_test.go:213: ParentsUntil=52
|
||||||
|
bench_traversal_test.go:213: ParentsUntil=52
|
||||||
|
bench_traversal_test.go:213: ParentsUntil=52
|
||||||
|
BenchmarkParentsUntilSelection 10000 157639 ns/op
|
||||||
|
--- BENCH: BenchmarkParentsUntilSelection
|
||||||
|
bench_traversal_test.go:230: ParentsUntilSelection=70
|
||||||
|
bench_traversal_test.go:230: ParentsUntilSelection=70
|
||||||
|
bench_traversal_test.go:230: ParentsUntilSelection=70
|
||||||
|
BenchmarkParentsUntilNodes 10000 157510 ns/op
|
||||||
|
--- BENCH: BenchmarkParentsUntilNodes
|
||||||
|
bench_traversal_test.go:248: ParentsUntilNodes=70
|
||||||
|
bench_traversal_test.go:248: ParentsUntilNodes=70
|
||||||
|
bench_traversal_test.go:248: ParentsUntilNodes=70
|
||||||
|
BenchmarkParentsFilteredUntil 100000 16987 ns/op
|
||||||
|
--- BENCH: BenchmarkParentsFilteredUntil
|
||||||
|
bench_traversal_test.go:264: ParentsFilteredUntil=2
|
||||||
|
bench_traversal_test.go:264: ParentsFilteredUntil=2
|
||||||
|
bench_traversal_test.go:264: ParentsFilteredUntil=2
|
||||||
|
bench_traversal_test.go:264: ParentsFilteredUntil=2
|
||||||
|
BenchmarkParentsFilteredUntilSelection 100000 21174 ns/op
|
||||||
|
--- BENCH: BenchmarkParentsFilteredUntilSelection
|
||||||
|
bench_traversal_test.go:281: ParentsFilteredUntilSelection=2
|
||||||
|
bench_traversal_test.go:281: ParentsFilteredUntilSelection=2
|
||||||
|
bench_traversal_test.go:281: ParentsFilteredUntilSelection=2
|
||||||
|
bench_traversal_test.go:281: ParentsFilteredUntilSelection=2
|
||||||
|
BenchmarkParentsFilteredUntilNodes 100000 21238 ns/op
|
||||||
|
--- BENCH: BenchmarkParentsFilteredUntilNodes
|
||||||
|
bench_traversal_test.go:299: ParentsFilteredUntilNodes=2
|
||||||
|
bench_traversal_test.go:299: ParentsFilteredUntilNodes=2
|
||||||
|
bench_traversal_test.go:299: ParentsFilteredUntilNodes=2
|
||||||
|
bench_traversal_test.go:299: ParentsFilteredUntilNodes=2
|
||||||
|
BenchmarkSiblings 50000 66536 ns/op
|
||||||
|
--- BENCH: BenchmarkSiblings
|
||||||
|
bench_traversal_test.go:315: Siblings=293
|
||||||
|
bench_traversal_test.go:315: Siblings=293
|
||||||
|
bench_traversal_test.go:315: Siblings=293
|
||||||
|
bench_traversal_test.go:315: Siblings=293
|
||||||
|
BenchmarkSiblingsFiltered 50000 71822 ns/op
|
||||||
|
--- BENCH: BenchmarkSiblingsFiltered
|
||||||
|
bench_traversal_test.go:331: SiblingsFiltered=46
|
||||||
|
bench_traversal_test.go:331: SiblingsFiltered=46
|
||||||
|
bench_traversal_test.go:331: SiblingsFiltered=46
|
||||||
|
bench_traversal_test.go:331: SiblingsFiltered=46
|
||||||
|
BenchmarkNext 200000 10745 ns/op
|
||||||
|
--- BENCH: BenchmarkNext
|
||||||
|
bench_traversal_test.go:347: Next=49
|
||||||
|
bench_traversal_test.go:347: Next=49
|
||||||
|
bench_traversal_test.go:347: Next=49
|
||||||
|
bench_traversal_test.go:347: Next=49
|
||||||
|
BenchmarkNextFiltered 200000 12399 ns/op
|
||||||
|
--- BENCH: BenchmarkNextFiltered
|
||||||
|
bench_traversal_test.go:363: NextFiltered=6
|
||||||
|
bench_traversal_test.go:363: NextFiltered=6
|
||||||
|
bench_traversal_test.go:363: NextFiltered=6
|
||||||
|
bench_traversal_test.go:363: NextFiltered=6
|
||||||
|
BenchmarkNextAll 50000 44640 ns/op
|
||||||
|
--- BENCH: BenchmarkNextAll
|
||||||
|
bench_traversal_test.go:379: NextAll=234
|
||||||
|
bench_traversal_test.go:379: NextAll=234
|
||||||
|
bench_traversal_test.go:379: NextAll=234
|
||||||
|
bench_traversal_test.go:379: NextAll=234
|
||||||
|
BenchmarkNextAllFiltered 50000 49713 ns/op
|
||||||
|
--- BENCH: BenchmarkNextAllFiltered
|
||||||
|
bench_traversal_test.go:395: NextAllFiltered=33
|
||||||
|
bench_traversal_test.go:395: NextAllFiltered=33
|
||||||
|
bench_traversal_test.go:395: NextAllFiltered=33
|
||||||
|
bench_traversal_test.go:395: NextAllFiltered=33
|
||||||
|
BenchmarkPrev 200000 10743 ns/op
|
||||||
|
--- BENCH: BenchmarkPrev
|
||||||
|
bench_traversal_test.go:411: Prev=49
|
||||||
|
bench_traversal_test.go:411: Prev=49
|
||||||
|
bench_traversal_test.go:411: Prev=49
|
||||||
|
bench_traversal_test.go:411: Prev=49
|
||||||
|
BenchmarkPrevFiltered 200000 12456 ns/op
|
||||||
|
--- BENCH: BenchmarkPrevFiltered
|
||||||
|
bench_traversal_test.go:429: PrevFiltered=7
|
||||||
|
bench_traversal_test.go:429: PrevFiltered=7
|
||||||
|
bench_traversal_test.go:429: PrevFiltered=7
|
||||||
|
bench_traversal_test.go:429: PrevFiltered=7
|
||||||
|
BenchmarkPrevAll 100000 17600 ns/op
|
||||||
|
--- BENCH: BenchmarkPrevAll
|
||||||
|
bench_traversal_test.go:445: PrevAll=78
|
||||||
|
bench_traversal_test.go:445: PrevAll=78
|
||||||
|
bench_traversal_test.go:445: PrevAll=78
|
||||||
|
bench_traversal_test.go:445: PrevAll=78
|
||||||
|
BenchmarkPrevAllFiltered 100000 19460 ns/op
|
||||||
|
--- BENCH: BenchmarkPrevAllFiltered
|
||||||
|
bench_traversal_test.go:461: PrevAllFiltered=6
|
||||||
|
bench_traversal_test.go:461: PrevAllFiltered=6
|
||||||
|
bench_traversal_test.go:461: PrevAllFiltered=6
|
||||||
|
bench_traversal_test.go:461: PrevAllFiltered=6
|
||||||
|
BenchmarkNextUntil 20000 92630 ns/op
|
||||||
|
--- BENCH: BenchmarkNextUntil
|
||||||
|
bench_traversal_test.go:477: NextUntil=84
|
||||||
|
bench_traversal_test.go:477: NextUntil=84
|
||||||
|
bench_traversal_test.go:477: NextUntil=84
|
||||||
|
bench_traversal_test.go:477: NextUntil=84
|
||||||
|
BenchmarkNextUntilSelection 50000 61285 ns/op
|
||||||
|
--- BENCH: BenchmarkNextUntilSelection
|
||||||
|
bench_traversal_test.go:494: NextUntilSelection=42
|
||||||
|
bench_traversal_test.go:494: NextUntilSelection=42
|
||||||
|
bench_traversal_test.go:494: NextUntilSelection=42
|
||||||
|
bench_traversal_test.go:494: NextUntilSelection=42
|
||||||
|
BenchmarkNextUntilNodes 100000 25859 ns/op
|
||||||
|
--- BENCH: BenchmarkNextUntilNodes
|
||||||
|
bench_traversal_test.go:512: NextUntilNodes=12
|
||||||
|
bench_traversal_test.go:512: NextUntilNodes=12
|
||||||
|
bench_traversal_test.go:512: NextUntilNodes=12
|
||||||
|
bench_traversal_test.go:512: NextUntilNodes=12
|
||||||
|
BenchmarkPrevUntil 10000 230236 ns/op
|
||||||
|
--- BENCH: BenchmarkPrevUntil
|
||||||
|
bench_traversal_test.go:528: PrevUntil=238
|
||||||
|
bench_traversal_test.go:528: PrevUntil=238
|
||||||
|
bench_traversal_test.go:528: PrevUntil=238
|
||||||
|
BenchmarkPrevUntilSelection 20000 77837 ns/op
|
||||||
|
--- BENCH: BenchmarkPrevUntilSelection
|
||||||
|
bench_traversal_test.go:545: PrevUntilSelection=49
|
||||||
|
bench_traversal_test.go:545: PrevUntilSelection=49
|
||||||
|
bench_traversal_test.go:545: PrevUntilSelection=49
|
||||||
|
bench_traversal_test.go:545: PrevUntilSelection=49
|
||||||
|
BenchmarkPrevUntilNodes 100000 20784 ns/op
|
||||||
|
--- BENCH: BenchmarkPrevUntilNodes
|
||||||
|
bench_traversal_test.go:563: PrevUntilNodes=11
|
||||||
|
bench_traversal_test.go:563: PrevUntilNodes=11
|
||||||
|
bench_traversal_test.go:563: PrevUntilNodes=11
|
||||||
|
bench_traversal_test.go:563: PrevUntilNodes=11
|
||||||
|
BenchmarkNextFilteredUntil 50000 46147 ns/op
|
||||||
|
--- BENCH: BenchmarkNextFilteredUntil
|
||||||
|
bench_traversal_test.go:579: NextFilteredUntil=22
|
||||||
|
bench_traversal_test.go:579: NextFilteredUntil=22
|
||||||
|
bench_traversal_test.go:579: NextFilteredUntil=22
|
||||||
|
bench_traversal_test.go:579: NextFilteredUntil=22
|
||||||
|
BenchmarkNextFilteredUntilSelection 50000 67164 ns/op
|
||||||
|
--- BENCH: BenchmarkNextFilteredUntilSelection
|
||||||
|
bench_traversal_test.go:596: NextFilteredUntilSelection=22
|
||||||
|
bench_traversal_test.go:596: NextFilteredUntilSelection=22
|
||||||
|
bench_traversal_test.go:596: NextFilteredUntilSelection=22
|
||||||
|
bench_traversal_test.go:596: NextFilteredUntilSelection=22
|
||||||
|
BenchmarkNextFilteredUntilNodes 50000 66628 ns/op
|
||||||
|
--- BENCH: BenchmarkNextFilteredUntilNodes
|
||||||
|
bench_traversal_test.go:614: NextFilteredUntilNodes=22
|
||||||
|
bench_traversal_test.go:614: NextFilteredUntilNodes=22
|
||||||
|
bench_traversal_test.go:614: NextFilteredUntilNodes=22
|
||||||
|
bench_traversal_test.go:614: NextFilteredUntilNodes=22
|
||||||
|
BenchmarkPrevFilteredUntil 50000 46697 ns/op
|
||||||
|
--- BENCH: BenchmarkPrevFilteredUntil
|
||||||
|
bench_traversal_test.go:630: PrevFilteredUntil=20
|
||||||
|
bench_traversal_test.go:630: PrevFilteredUntil=20
|
||||||
|
bench_traversal_test.go:630: PrevFilteredUntil=20
|
||||||
|
bench_traversal_test.go:630: PrevFilteredUntil=20
|
||||||
|
BenchmarkPrevFilteredUntilSelection 50000 68646 ns/op
|
||||||
|
--- BENCH: BenchmarkPrevFilteredUntilSelection
|
||||||
|
bench_traversal_test.go:647: PrevFilteredUntilSelection=20
|
||||||
|
bench_traversal_test.go:647: PrevFilteredUntilSelection=20
|
||||||
|
bench_traversal_test.go:647: PrevFilteredUntilSelection=20
|
||||||
|
bench_traversal_test.go:647: PrevFilteredUntilSelection=20
|
||||||
|
BenchmarkPrevFilteredUntilNodes 50000 68745 ns/op
|
||||||
|
--- BENCH: BenchmarkPrevFilteredUntilNodes
|
||||||
|
bench_traversal_test.go:665: PrevFilteredUntilNodes=20
|
||||||
|
bench_traversal_test.go:665: PrevFilteredUntilNodes=20
|
||||||
|
bench_traversal_test.go:665: PrevFilteredUntilNodes=20
|
||||||
|
bench_traversal_test.go:665: PrevFilteredUntilNodes=20
|
||||||
|
BenchmarkClosest 500000 4909 ns/op
|
||||||
|
--- BENCH: BenchmarkClosest
|
||||||
|
bench_traversal_test.go:681: Closest=2
|
||||||
|
bench_traversal_test.go:681: Closest=2
|
||||||
|
bench_traversal_test.go:681: Closest=2
|
||||||
|
bench_traversal_test.go:681: Closest=2
|
||||||
|
BenchmarkClosestSelection 5000000 744 ns/op
|
||||||
|
--- BENCH: BenchmarkClosestSelection
|
||||||
|
bench_traversal_test.go:698: ClosestSelection=2
|
||||||
|
bench_traversal_test.go:698: ClosestSelection=2
|
||||||
|
bench_traversal_test.go:698: ClosestSelection=2
|
||||||
|
bench_traversal_test.go:698: ClosestSelection=2
|
||||||
|
bench_traversal_test.go:698: ClosestSelection=2
|
||||||
|
BenchmarkClosestNodes 5000000 733 ns/op
|
||||||
|
--- BENCH: BenchmarkClosestNodes
|
||||||
|
bench_traversal_test.go:715: ClosestNodes=2
|
||||||
|
bench_traversal_test.go:715: ClosestNodes=2
|
||||||
|
bench_traversal_test.go:715: ClosestNodes=2
|
||||||
|
bench_traversal_test.go:715: ClosestNodes=2
|
||||||
|
bench_traversal_test.go:715: ClosestNodes=2
|
||||||
|
ok github.com/PuerkitoBio/goquery 220.793s
|
476
Godeps/_workspace/src/github.com/PuerkitoBio/goquery/bench/v0.3.0
generated
vendored
Normal file
476
Godeps/_workspace/src/github.com/PuerkitoBio/goquery/bench/v0.3.0
generated
vendored
Normal file
|
@ -0,0 +1,476 @@
|
||||||
|
PASS
|
||||||
|
BenchmarkFirst 20000000 95.5 ns/op
|
||||||
|
BenchmarkLast 20000000 94.9 ns/op
|
||||||
|
BenchmarkEq 20000000 95.7 ns/op
|
||||||
|
BenchmarkSlice 20000000 91.7 ns/op
|
||||||
|
BenchmarkGet 1000000000 2.05 ns/op
|
||||||
|
BenchmarkIndex 1000000 1079 ns/op
|
||||||
|
--- BENCH: BenchmarkIndex
|
||||||
|
bench_array_test.go:73: Index=3
|
||||||
|
bench_array_test.go:73: Index=3
|
||||||
|
bench_array_test.go:73: Index=3
|
||||||
|
bench_array_test.go:73: Index=3
|
||||||
|
BenchmarkIndexSelector 100000 26972 ns/op
|
||||||
|
--- BENCH: BenchmarkIndexSelector
|
||||||
|
bench_array_test.go:85: IndexSelector=4
|
||||||
|
bench_array_test.go:85: IndexSelector=4
|
||||||
|
bench_array_test.go:85: IndexSelector=4
|
||||||
|
bench_array_test.go:85: IndexSelector=4
|
||||||
|
BenchmarkIndexOfNode 100000000 10.8 ns/op
|
||||||
|
--- BENCH: BenchmarkIndexOfNode
|
||||||
|
bench_array_test.go:99: IndexOfNode=2
|
||||||
|
bench_array_test.go:99: IndexOfNode=2
|
||||||
|
bench_array_test.go:99: IndexOfNode=2
|
||||||
|
bench_array_test.go:99: IndexOfNode=2
|
||||||
|
bench_array_test.go:99: IndexOfNode=2
|
||||||
|
BenchmarkIndexOfSelection 100000000 11.7 ns/op
|
||||||
|
--- BENCH: BenchmarkIndexOfSelection
|
||||||
|
bench_array_test.go:111: IndexOfSelection=2
|
||||||
|
bench_array_test.go:111: IndexOfSelection=2
|
||||||
|
bench_array_test.go:111: IndexOfSelection=2
|
||||||
|
bench_array_test.go:111: IndexOfSelection=2
|
||||||
|
bench_array_test.go:111: IndexOfSelection=2
|
||||||
|
BenchmarkMetalReviewExample 10000 213800 ns/op
|
||||||
|
--- BENCH: BenchmarkMetalReviewExample
|
||||||
|
bench_example_test.go:40: Review 0: Midnight - Complete and Total Hell (8.5).
|
||||||
|
Review 1: Over Your Threshold - Facticity (6.0).
|
||||||
|
Review 2: Nuclear Death Terror - Chaos Reigns (7.5).
|
||||||
|
Review 3: Evoken - Atra Mors (9.5).
|
||||||
|
|
||||||
|
bench_example_test.go:41: MetalReviewExample=10
|
||||||
|
bench_example_test.go:40: Review 0: Midnight - Complete and Total Hell (8.5).
|
||||||
|
Review 1: Over Your Threshold - Facticity (6.0).
|
||||||
|
Review 2: Nuclear Death Terror - Chaos Reigns (7.5).
|
||||||
|
Review 3: Evoken - Atra Mors (9.5).
|
||||||
|
... [output truncated]
|
||||||
|
BenchmarkAdd 100000 21811 ns/op
|
||||||
|
--- BENCH: BenchmarkAdd
|
||||||
|
bench_expand_test.go:20: Add=43
|
||||||
|
bench_expand_test.go:20: Add=43
|
||||||
|
bench_expand_test.go:20: Add=43
|
||||||
|
bench_expand_test.go:20: Add=43
|
||||||
|
BenchmarkAddSelection 10000000 205 ns/op
|
||||||
|
--- BENCH: BenchmarkAddSelection
|
||||||
|
bench_expand_test.go:37: AddSelection=43
|
||||||
|
bench_expand_test.go:37: AddSelection=43
|
||||||
|
bench_expand_test.go:37: AddSelection=43
|
||||||
|
bench_expand_test.go:37: AddSelection=43
|
||||||
|
bench_expand_test.go:37: AddSelection=43
|
||||||
|
BenchmarkAddNodes 10000000 202 ns/op
|
||||||
|
--- BENCH: BenchmarkAddNodes
|
||||||
|
bench_expand_test.go:55: AddNodes=43
|
||||||
|
bench_expand_test.go:55: AddNodes=43
|
||||||
|
bench_expand_test.go:55: AddNodes=43
|
||||||
|
bench_expand_test.go:55: AddNodes=43
|
||||||
|
bench_expand_test.go:55: AddNodes=43
|
||||||
|
BenchmarkAndSelf 1000000 2467 ns/op
|
||||||
|
--- BENCH: BenchmarkAndSelf
|
||||||
|
bench_expand_test.go:71: AndSelf=44
|
||||||
|
bench_expand_test.go:71: AndSelf=44
|
||||||
|
bench_expand_test.go:71: AndSelf=44
|
||||||
|
bench_expand_test.go:71: AndSelf=44
|
||||||
|
BenchmarkFilter 100000 25643 ns/op
|
||||||
|
--- BENCH: BenchmarkFilter
|
||||||
|
bench_filter_test.go:20: Filter=13
|
||||||
|
bench_filter_test.go:20: Filter=13
|
||||||
|
bench_filter_test.go:20: Filter=13
|
||||||
|
bench_filter_test.go:20: Filter=13
|
||||||
|
BenchmarkNot 100000 29566 ns/op
|
||||||
|
--- BENCH: BenchmarkNot
|
||||||
|
bench_filter_test.go:36: Not=371
|
||||||
|
bench_filter_test.go:36: Not=371
|
||||||
|
bench_filter_test.go:36: Not=371
|
||||||
|
bench_filter_test.go:36: Not=371
|
||||||
|
BenchmarkFilterFunction 50000 66894 ns/op
|
||||||
|
--- BENCH: BenchmarkFilterFunction
|
||||||
|
bench_filter_test.go:55: FilterFunction=112
|
||||||
|
bench_filter_test.go:55: FilterFunction=112
|
||||||
|
bench_filter_test.go:55: FilterFunction=112
|
||||||
|
bench_filter_test.go:55: FilterFunction=112
|
||||||
|
BenchmarkNotFunction 50000 72183 ns/op
|
||||||
|
--- BENCH: BenchmarkNotFunction
|
||||||
|
bench_filter_test.go:74: NotFunction=261
|
||||||
|
bench_filter_test.go:74: NotFunction=261
|
||||||
|
bench_filter_test.go:74: NotFunction=261
|
||||||
|
bench_filter_test.go:74: NotFunction=261
|
||||||
|
BenchmarkFilterNodes 50000 65516 ns/op
|
||||||
|
--- BENCH: BenchmarkFilterNodes
|
||||||
|
bench_filter_test.go:92: FilterNodes=2
|
||||||
|
bench_filter_test.go:92: FilterNodes=2
|
||||||
|
bench_filter_test.go:92: FilterNodes=2
|
||||||
|
bench_filter_test.go:92: FilterNodes=2
|
||||||
|
BenchmarkNotNodes 20000 78880 ns/op
|
||||||
|
--- BENCH: BenchmarkNotNodes
|
||||||
|
bench_filter_test.go:110: NotNodes=360
|
||||||
|
bench_filter_test.go:110: NotNodes=360
|
||||||
|
bench_filter_test.go:110: NotNodes=360
|
||||||
|
bench_filter_test.go:110: NotNodes=360
|
||||||
|
BenchmarkFilterSelection 50000 65232 ns/op
|
||||||
|
--- BENCH: BenchmarkFilterSelection
|
||||||
|
bench_filter_test.go:127: FilterSelection=2
|
||||||
|
bench_filter_test.go:127: FilterSelection=2
|
||||||
|
bench_filter_test.go:127: FilterSelection=2
|
||||||
|
bench_filter_test.go:127: FilterSelection=2
|
||||||
|
BenchmarkNotSelection 20000 78813 ns/op
|
||||||
|
--- BENCH: BenchmarkNotSelection
|
||||||
|
bench_filter_test.go:144: NotSelection=360
|
||||||
|
bench_filter_test.go:144: NotSelection=360
|
||||||
|
bench_filter_test.go:144: NotSelection=360
|
||||||
|
bench_filter_test.go:144: NotSelection=360
|
||||||
|
BenchmarkHas 5000 388834 ns/op
|
||||||
|
--- BENCH: BenchmarkHas
|
||||||
|
bench_filter_test.go:160: Has=13
|
||||||
|
bench_filter_test.go:160: Has=13
|
||||||
|
bench_filter_test.go:160: Has=13
|
||||||
|
BenchmarkHasNodes 10000 228552 ns/op
|
||||||
|
--- BENCH: BenchmarkHasNodes
|
||||||
|
bench_filter_test.go:178: HasNodes=15
|
||||||
|
bench_filter_test.go:178: HasNodes=15
|
||||||
|
bench_filter_test.go:178: HasNodes=15
|
||||||
|
BenchmarkHasSelection 10000 228365 ns/op
|
||||||
|
--- BENCH: BenchmarkHasSelection
|
||||||
|
bench_filter_test.go:195: HasSelection=15
|
||||||
|
bench_filter_test.go:195: HasSelection=15
|
||||||
|
bench_filter_test.go:195: HasSelection=15
|
||||||
|
BenchmarkEnd 500000000 4.62 ns/op
|
||||||
|
--- BENCH: BenchmarkEnd
|
||||||
|
bench_filter_test.go:211: End=373
|
||||||
|
bench_filter_test.go:211: End=373
|
||||||
|
bench_filter_test.go:211: End=373
|
||||||
|
bench_filter_test.go:211: End=373
|
||||||
|
bench_filter_test.go:211: End=373
|
||||||
|
bench_filter_test.go:211: End=373
|
||||||
|
BenchmarkEach 200000 9548 ns/op
|
||||||
|
--- BENCH: BenchmarkEach
|
||||||
|
bench_iteration_test.go:22: Each=59
|
||||||
|
bench_iteration_test.go:22: Each=59
|
||||||
|
bench_iteration_test.go:22: Each=59
|
||||||
|
bench_iteration_test.go:22: Each=59
|
||||||
|
BenchmarkMap 100000 15900 ns/op
|
||||||
|
--- BENCH: BenchmarkMap
|
||||||
|
bench_iteration_test.go:41: Map=59
|
||||||
|
bench_iteration_test.go:41: Map=59
|
||||||
|
bench_iteration_test.go:41: Map=59
|
||||||
|
bench_iteration_test.go:41: Map=59
|
||||||
|
BenchmarkEachWithBreak 1000000 1650 ns/op
|
||||||
|
--- BENCH: BenchmarkEachWithBreak
|
||||||
|
bench_iteration_test.go:61: Each=10
|
||||||
|
bench_iteration_test.go:61: Each=10
|
||||||
|
bench_iteration_test.go:61: Each=10
|
||||||
|
bench_iteration_test.go:61: Each=10
|
||||||
|
BenchmarkAttr 50000000 30.5 ns/op
|
||||||
|
--- BENCH: BenchmarkAttr
|
||||||
|
bench_property_test.go:16: Attr=firstHeading
|
||||||
|
bench_property_test.go:16: Attr=firstHeading
|
||||||
|
bench_property_test.go:16: Attr=firstHeading
|
||||||
|
bench_property_test.go:16: Attr=firstHeading
|
||||||
|
bench_property_test.go:16: Attr=firstHeading
|
||||||
|
BenchmarkText 100000 18873 ns/op
|
||||||
|
BenchmarkLength 2000000000 0.31 ns/op
|
||||||
|
--- BENCH: BenchmarkLength
|
||||||
|
bench_property_test.go:37: Length=14
|
||||||
|
bench_property_test.go:37: Length=14
|
||||||
|
bench_property_test.go:37: Length=14
|
||||||
|
bench_property_test.go:37: Length=14
|
||||||
|
bench_property_test.go:37: Length=14
|
||||||
|
bench_property_test.go:37: Length=14
|
||||||
|
BenchmarkHtml 5000000 616 ns/op
|
||||||
|
BenchmarkIs 100000 29499 ns/op
|
||||||
|
--- BENCH: BenchmarkIs
|
||||||
|
bench_query_test.go:16: Is=true
|
||||||
|
bench_query_test.go:16: Is=true
|
||||||
|
bench_query_test.go:16: Is=true
|
||||||
|
bench_query_test.go:16: Is=true
|
||||||
|
BenchmarkIsPositional 100000 23733 ns/op
|
||||||
|
--- BENCH: BenchmarkIsPositional
|
||||||
|
bench_query_test.go:28: IsPositional=true
|
||||||
|
bench_query_test.go:28: IsPositional=true
|
||||||
|
bench_query_test.go:28: IsPositional=true
|
||||||
|
bench_query_test.go:28: IsPositional=true
|
||||||
|
BenchmarkIsFunction 1000000 2404 ns/op
|
||||||
|
--- BENCH: BenchmarkIsFunction
|
||||||
|
bench_query_test.go:43: IsFunction=true
|
||||||
|
bench_query_test.go:43: IsFunction=true
|
||||||
|
bench_query_test.go:43: IsFunction=true
|
||||||
|
bench_query_test.go:43: IsFunction=true
|
||||||
|
BenchmarkIsSelection 50000 65376 ns/op
|
||||||
|
--- BENCH: BenchmarkIsSelection
|
||||||
|
bench_query_test.go:56: IsSelection=true
|
||||||
|
bench_query_test.go:56: IsSelection=true
|
||||||
|
bench_query_test.go:56: IsSelection=true
|
||||||
|
bench_query_test.go:56: IsSelection=true
|
||||||
|
BenchmarkIsNodes 50000 65322 ns/op
|
||||||
|
--- BENCH: BenchmarkIsNodes
|
||||||
|
bench_query_test.go:70: IsNodes=true
|
||||||
|
bench_query_test.go:70: IsNodes=true
|
||||||
|
bench_query_test.go:70: IsNodes=true
|
||||||
|
bench_query_test.go:70: IsNodes=true
|
||||||
|
BenchmarkHasClass 5000 558933 ns/op
|
||||||
|
--- BENCH: BenchmarkHasClass
|
||||||
|
bench_query_test.go:82: HasClass=true
|
||||||
|
bench_query_test.go:82: HasClass=true
|
||||||
|
bench_query_test.go:82: HasClass=true
|
||||||
|
BenchmarkContains 100000000 11.1 ns/op
|
||||||
|
--- BENCH: BenchmarkContains
|
||||||
|
bench_query_test.go:96: Contains=true
|
||||||
|
bench_query_test.go:96: Contains=true
|
||||||
|
bench_query_test.go:96: Contains=true
|
||||||
|
bench_query_test.go:96: Contains=true
|
||||||
|
bench_query_test.go:96: Contains=true
|
||||||
|
BenchmarkFind 100000 27841 ns/op
|
||||||
|
--- BENCH: BenchmarkFind
|
||||||
|
bench_traversal_test.go:18: Find=41
|
||||||
|
bench_traversal_test.go:18: Find=41
|
||||||
|
bench_traversal_test.go:18: Find=41
|
||||||
|
bench_traversal_test.go:18: Find=41
|
||||||
|
BenchmarkFindWithinSelection 50000 72096 ns/op
|
||||||
|
--- BENCH: BenchmarkFindWithinSelection
|
||||||
|
bench_traversal_test.go:34: FindWithinSelection=39
|
||||||
|
bench_traversal_test.go:34: FindWithinSelection=39
|
||||||
|
bench_traversal_test.go:34: FindWithinSelection=39
|
||||||
|
bench_traversal_test.go:34: FindWithinSelection=39
|
||||||
|
BenchmarkFindSelection 5000 457349 ns/op
|
||||||
|
--- BENCH: BenchmarkFindSelection
|
||||||
|
bench_traversal_test.go:51: FindSelection=73
|
||||||
|
bench_traversal_test.go:51: FindSelection=73
|
||||||
|
bench_traversal_test.go:51: FindSelection=73
|
||||||
|
BenchmarkFindNodes 5000 459324 ns/op
|
||||||
|
--- BENCH: BenchmarkFindNodes
|
||||||
|
bench_traversal_test.go:69: FindNodes=73
|
||||||
|
bench_traversal_test.go:69: FindNodes=73
|
||||||
|
bench_traversal_test.go:69: FindNodes=73
|
||||||
|
BenchmarkContents 500000 3435 ns/op
|
||||||
|
--- BENCH: BenchmarkContents
|
||||||
|
bench_traversal_test.go:85: Contents=16
|
||||||
|
bench_traversal_test.go:85: Contents=16
|
||||||
|
bench_traversal_test.go:85: Contents=16
|
||||||
|
bench_traversal_test.go:85: Contents=16
|
||||||
|
BenchmarkContentsFiltered 500000 5241 ns/op
|
||||||
|
--- BENCH: BenchmarkContentsFiltered
|
||||||
|
bench_traversal_test.go:101: ContentsFiltered=1
|
||||||
|
bench_traversal_test.go:101: ContentsFiltered=1
|
||||||
|
bench_traversal_test.go:101: ContentsFiltered=1
|
||||||
|
bench_traversal_test.go:101: ContentsFiltered=1
|
||||||
|
BenchmarkChildren 5000000 667 ns/op
|
||||||
|
--- BENCH: BenchmarkChildren
|
||||||
|
bench_traversal_test.go:117: Children=2
|
||||||
|
bench_traversal_test.go:117: Children=2
|
||||||
|
bench_traversal_test.go:117: Children=2
|
||||||
|
bench_traversal_test.go:117: Children=2
|
||||||
|
bench_traversal_test.go:117: Children=2
|
||||||
|
BenchmarkChildrenFiltered 500000 3639 ns/op
|
||||||
|
--- BENCH: BenchmarkChildrenFiltered
|
||||||
|
bench_traversal_test.go:133: ChildrenFiltered=2
|
||||||
|
bench_traversal_test.go:133: ChildrenFiltered=2
|
||||||
|
bench_traversal_test.go:133: ChildrenFiltered=2
|
||||||
|
bench_traversal_test.go:133: ChildrenFiltered=2
|
||||||
|
BenchmarkParent 50000 44867 ns/op
|
||||||
|
--- BENCH: BenchmarkParent
|
||||||
|
bench_traversal_test.go:149: Parent=55
|
||||||
|
bench_traversal_test.go:149: Parent=55
|
||||||
|
bench_traversal_test.go:149: Parent=55
|
||||||
|
bench_traversal_test.go:149: Parent=55
|
||||||
|
BenchmarkParentFiltered 50000 46476 ns/op
|
||||||
|
--- BENCH: BenchmarkParentFiltered
|
||||||
|
bench_traversal_test.go:165: ParentFiltered=4
|
||||||
|
bench_traversal_test.go:165: ParentFiltered=4
|
||||||
|
bench_traversal_test.go:165: ParentFiltered=4
|
||||||
|
bench_traversal_test.go:165: ParentFiltered=4
|
||||||
|
BenchmarkParents 20000 92559 ns/op
|
||||||
|
--- BENCH: BenchmarkParents
|
||||||
|
bench_traversal_test.go:181: Parents=73
|
||||||
|
bench_traversal_test.go:181: Parents=73
|
||||||
|
bench_traversal_test.go:181: Parents=73
|
||||||
|
bench_traversal_test.go:181: Parents=73
|
||||||
|
BenchmarkParentsFiltered 20000 96142 ns/op
|
||||||
|
--- BENCH: BenchmarkParentsFiltered
|
||||||
|
bench_traversal_test.go:197: ParentsFiltered=18
|
||||||
|
bench_traversal_test.go:197: ParentsFiltered=18
|
||||||
|
bench_traversal_test.go:197: ParentsFiltered=18
|
||||||
|
bench_traversal_test.go:197: ParentsFiltered=18
|
||||||
|
BenchmarkParentsUntil 50000 73931 ns/op
|
||||||
|
--- BENCH: BenchmarkParentsUntil
|
||||||
|
bench_traversal_test.go:213: ParentsUntil=52
|
||||||
|
bench_traversal_test.go:213: ParentsUntil=52
|
||||||
|
bench_traversal_test.go:213: ParentsUntil=52
|
||||||
|
bench_traversal_test.go:213: ParentsUntil=52
|
||||||
|
BenchmarkParentsUntilSelection 10000 159820 ns/op
|
||||||
|
--- BENCH: BenchmarkParentsUntilSelection
|
||||||
|
bench_traversal_test.go:230: ParentsUntilSelection=70
|
||||||
|
bench_traversal_test.go:230: ParentsUntilSelection=70
|
||||||
|
bench_traversal_test.go:230: ParentsUntilSelection=70
|
||||||
|
BenchmarkParentsUntilNodes 10000 158811 ns/op
|
||||||
|
--- BENCH: BenchmarkParentsUntilNodes
|
||||||
|
bench_traversal_test.go:248: ParentsUntilNodes=70
|
||||||
|
bench_traversal_test.go:248: ParentsUntilNodes=70
|
||||||
|
bench_traversal_test.go:248: ParentsUntilNodes=70
|
||||||
|
BenchmarkParentsFilteredUntil 100000 17203 ns/op
|
||||||
|
--- BENCH: BenchmarkParentsFilteredUntil
|
||||||
|
bench_traversal_test.go:264: ParentsFilteredUntil=2
|
||||||
|
bench_traversal_test.go:264: ParentsFilteredUntil=2
|
||||||
|
bench_traversal_test.go:264: ParentsFilteredUntil=2
|
||||||
|
bench_traversal_test.go:264: ParentsFilteredUntil=2
|
||||||
|
BenchmarkParentsFilteredUntilSelection 100000 21358 ns/op
|
||||||
|
--- BENCH: BenchmarkParentsFilteredUntilSelection
|
||||||
|
bench_traversal_test.go:281: ParentsFilteredUntilSelection=2
|
||||||
|
bench_traversal_test.go:281: ParentsFilteredUntilSelection=2
|
||||||
|
bench_traversal_test.go:281: ParentsFilteredUntilSelection=2
|
||||||
|
bench_traversal_test.go:281: ParentsFilteredUntilSelection=2
|
||||||
|
BenchmarkParentsFilteredUntilNodes 100000 21338 ns/op
|
||||||
|
--- BENCH: BenchmarkParentsFilteredUntilNodes
|
||||||
|
bench_traversal_test.go:299: ParentsFilteredUntilNodes=2
|
||||||
|
bench_traversal_test.go:299: ParentsFilteredUntilNodes=2
|
||||||
|
bench_traversal_test.go:299: ParentsFilteredUntilNodes=2
|
||||||
|
bench_traversal_test.go:299: ParentsFilteredUntilNodes=2
|
||||||
|
BenchmarkSiblings 50000 66463 ns/op
|
||||||
|
--- BENCH: BenchmarkSiblings
|
||||||
|
bench_traversal_test.go:315: Siblings=293
|
||||||
|
bench_traversal_test.go:315: Siblings=293
|
||||||
|
bench_traversal_test.go:315: Siblings=293
|
||||||
|
bench_traversal_test.go:315: Siblings=293
|
||||||
|
BenchmarkSiblingsFiltered 50000 72503 ns/op
|
||||||
|
--- BENCH: BenchmarkSiblingsFiltered
|
||||||
|
bench_traversal_test.go:331: SiblingsFiltered=46
|
||||||
|
bench_traversal_test.go:331: SiblingsFiltered=46
|
||||||
|
bench_traversal_test.go:331: SiblingsFiltered=46
|
||||||
|
bench_traversal_test.go:331: SiblingsFiltered=46
|
||||||
|
BenchmarkNext 200000 10881 ns/op
|
||||||
|
--- BENCH: BenchmarkNext
|
||||||
|
bench_traversal_test.go:347: Next=49
|
||||||
|
bench_traversal_test.go:347: Next=49
|
||||||
|
bench_traversal_test.go:347: Next=49
|
||||||
|
bench_traversal_test.go:347: Next=49
|
||||||
|
BenchmarkNextFiltered 200000 12588 ns/op
|
||||||
|
--- BENCH: BenchmarkNextFiltered
|
||||||
|
bench_traversal_test.go:363: NextFiltered=6
|
||||||
|
bench_traversal_test.go:363: NextFiltered=6
|
||||||
|
bench_traversal_test.go:363: NextFiltered=6
|
||||||
|
bench_traversal_test.go:363: NextFiltered=6
|
||||||
|
BenchmarkNextAll 50000 45075 ns/op
|
||||||
|
--- BENCH: BenchmarkNextAll
|
||||||
|
bench_traversal_test.go:379: NextAll=234
|
||||||
|
bench_traversal_test.go:379: NextAll=234
|
||||||
|
bench_traversal_test.go:379: NextAll=234
|
||||||
|
bench_traversal_test.go:379: NextAll=234
|
||||||
|
BenchmarkNextAllFiltered 50000 50455 ns/op
|
||||||
|
--- BENCH: BenchmarkNextAllFiltered
|
||||||
|
bench_traversal_test.go:395: NextAllFiltered=33
|
||||||
|
bench_traversal_test.go:395: NextAllFiltered=33
|
||||||
|
bench_traversal_test.go:395: NextAllFiltered=33
|
||||||
|
bench_traversal_test.go:395: NextAllFiltered=33
|
||||||
|
BenchmarkPrev 200000 10933 ns/op
|
||||||
|
--- BENCH: BenchmarkPrev
|
||||||
|
bench_traversal_test.go:411: Prev=49
|
||||||
|
bench_traversal_test.go:411: Prev=49
|
||||||
|
bench_traversal_test.go:411: Prev=49
|
||||||
|
bench_traversal_test.go:411: Prev=49
|
||||||
|
BenchmarkPrevFiltered 200000 12579 ns/op
|
||||||
|
--- BENCH: BenchmarkPrevFiltered
|
||||||
|
bench_traversal_test.go:429: PrevFiltered=7
|
||||||
|
bench_traversal_test.go:429: PrevFiltered=7
|
||||||
|
bench_traversal_test.go:429: PrevFiltered=7
|
||||||
|
bench_traversal_test.go:429: PrevFiltered=7
|
||||||
|
BenchmarkPrevAll 100000 17751 ns/op
|
||||||
|
--- BENCH: BenchmarkPrevAll
|
||||||
|
bench_traversal_test.go:445: PrevAll=78
|
||||||
|
bench_traversal_test.go:445: PrevAll=78
|
||||||
|
bench_traversal_test.go:445: PrevAll=78
|
||||||
|
bench_traversal_test.go:445: PrevAll=78
|
||||||
|
BenchmarkPrevAllFiltered 100000 19702 ns/op
|
||||||
|
--- BENCH: BenchmarkPrevAllFiltered
|
||||||
|
bench_traversal_test.go:461: PrevAllFiltered=6
|
||||||
|
bench_traversal_test.go:461: PrevAllFiltered=6
|
||||||
|
bench_traversal_test.go:461: PrevAllFiltered=6
|
||||||
|
bench_traversal_test.go:461: PrevAllFiltered=6
|
||||||
|
BenchmarkNextUntil 20000 93586 ns/op
|
||||||
|
--- BENCH: BenchmarkNextUntil
|
||||||
|
bench_traversal_test.go:477: NextUntil=84
|
||||||
|
bench_traversal_test.go:477: NextUntil=84
|
||||||
|
bench_traversal_test.go:477: NextUntil=84
|
||||||
|
bench_traversal_test.go:477: NextUntil=84
|
||||||
|
BenchmarkNextUntilSelection 50000 61155 ns/op
|
||||||
|
--- BENCH: BenchmarkNextUntilSelection
|
||||||
|
bench_traversal_test.go:494: NextUntilSelection=42
|
||||||
|
bench_traversal_test.go:494: NextUntilSelection=42
|
||||||
|
bench_traversal_test.go:494: NextUntilSelection=42
|
||||||
|
bench_traversal_test.go:494: NextUntilSelection=42
|
||||||
|
BenchmarkNextUntilNodes 100000 25805 ns/op
|
||||||
|
--- BENCH: BenchmarkNextUntilNodes
|
||||||
|
bench_traversal_test.go:512: NextUntilNodes=12
|
||||||
|
bench_traversal_test.go:512: NextUntilNodes=12
|
||||||
|
bench_traversal_test.go:512: NextUntilNodes=12
|
||||||
|
bench_traversal_test.go:512: NextUntilNodes=12
|
||||||
|
BenchmarkPrevUntil 10000 232225 ns/op
|
||||||
|
--- BENCH: BenchmarkPrevUntil
|
||||||
|
bench_traversal_test.go:528: PrevUntil=238
|
||||||
|
bench_traversal_test.go:528: PrevUntil=238
|
||||||
|
bench_traversal_test.go:528: PrevUntil=238
|
||||||
|
BenchmarkPrevUntilSelection 20000 78316 ns/op
|
||||||
|
--- BENCH: BenchmarkPrevUntilSelection
|
||||||
|
bench_traversal_test.go:545: PrevUntilSelection=49
|
||||||
|
bench_traversal_test.go:545: PrevUntilSelection=49
|
||||||
|
bench_traversal_test.go:545: PrevUntilSelection=49
|
||||||
|
bench_traversal_test.go:545: PrevUntilSelection=49
|
||||||
|
BenchmarkPrevUntilNodes 100000 20657 ns/op
|
||||||
|
--- BENCH: BenchmarkPrevUntilNodes
|
||||||
|
bench_traversal_test.go:563: PrevUntilNodes=11
|
||||||
|
bench_traversal_test.go:563: PrevUntilNodes=11
|
||||||
|
bench_traversal_test.go:563: PrevUntilNodes=11
|
||||||
|
bench_traversal_test.go:563: PrevUntilNodes=11
|
||||||
|
BenchmarkNextFilteredUntil 50000 46567 ns/op
|
||||||
|
--- BENCH: BenchmarkNextFilteredUntil
|
||||||
|
bench_traversal_test.go:579: NextFilteredUntil=22
|
||||||
|
bench_traversal_test.go:579: NextFilteredUntil=22
|
||||||
|
bench_traversal_test.go:579: NextFilteredUntil=22
|
||||||
|
bench_traversal_test.go:579: NextFilteredUntil=22
|
||||||
|
BenchmarkNextFilteredUntilSelection 50000 67227 ns/op
|
||||||
|
--- BENCH: BenchmarkNextFilteredUntilSelection
|
||||||
|
bench_traversal_test.go:596: NextFilteredUntilSelection=22
|
||||||
|
bench_traversal_test.go:596: NextFilteredUntilSelection=22
|
||||||
|
bench_traversal_test.go:596: NextFilteredUntilSelection=22
|
||||||
|
bench_traversal_test.go:596: NextFilteredUntilSelection=22
|
||||||
|
BenchmarkNextFilteredUntilNodes 50000 66995 ns/op
|
||||||
|
--- BENCH: BenchmarkNextFilteredUntilNodes
|
||||||
|
bench_traversal_test.go:614: NextFilteredUntilNodes=22
|
||||||
|
bench_traversal_test.go:614: NextFilteredUntilNodes=22
|
||||||
|
bench_traversal_test.go:614: NextFilteredUntilNodes=22
|
||||||
|
bench_traversal_test.go:614: NextFilteredUntilNodes=22
|
||||||
|
BenchmarkPrevFilteredUntil 50000 47361 ns/op
|
||||||
|
--- BENCH: BenchmarkPrevFilteredUntil
|
||||||
|
bench_traversal_test.go:630: PrevFilteredUntil=20
|
||||||
|
bench_traversal_test.go:630: PrevFilteredUntil=20
|
||||||
|
bench_traversal_test.go:630: PrevFilteredUntil=20
|
||||||
|
bench_traversal_test.go:630: PrevFilteredUntil=20
|
||||||
|
BenchmarkPrevFilteredUntilSelection 50000 68802 ns/op
|
||||||
|
--- BENCH: BenchmarkPrevFilteredUntilSelection
|
||||||
|
bench_traversal_test.go:647: PrevFilteredUntilSelection=20
|
||||||
|
bench_traversal_test.go:647: PrevFilteredUntilSelection=20
|
||||||
|
bench_traversal_test.go:647: PrevFilteredUntilSelection=20
|
||||||
|
bench_traversal_test.go:647: PrevFilteredUntilSelection=20
|
||||||
|
BenchmarkPrevFilteredUntilNodes 50000 68928 ns/op
|
||||||
|
--- BENCH: BenchmarkPrevFilteredUntilNodes
|
||||||
|
bench_traversal_test.go:665: PrevFilteredUntilNodes=20
|
||||||
|
bench_traversal_test.go:665: PrevFilteredUntilNodes=20
|
||||||
|
bench_traversal_test.go:665: PrevFilteredUntilNodes=20
|
||||||
|
bench_traversal_test.go:665: PrevFilteredUntilNodes=20
|
||||||
|
BenchmarkClosest 500000 4922 ns/op
|
||||||
|
--- BENCH: BenchmarkClosest
|
||||||
|
bench_traversal_test.go:681: Closest=2
|
||||||
|
bench_traversal_test.go:681: Closest=2
|
||||||
|
bench_traversal_test.go:681: Closest=2
|
||||||
|
bench_traversal_test.go:681: Closest=2
|
||||||
|
BenchmarkClosestSelection 5000000 738 ns/op
|
||||||
|
--- BENCH: BenchmarkClosestSelection
|
||||||
|
bench_traversal_test.go:698: ClosestSelection=2
|
||||||
|
bench_traversal_test.go:698: ClosestSelection=2
|
||||||
|
bench_traversal_test.go:698: ClosestSelection=2
|
||||||
|
bench_traversal_test.go:698: ClosestSelection=2
|
||||||
|
bench_traversal_test.go:698: ClosestSelection=2
|
||||||
|
BenchmarkClosestNodes 5000000 737 ns/op
|
||||||
|
--- BENCH: BenchmarkClosestNodes
|
||||||
|
bench_traversal_test.go:715: ClosestNodes=2
|
||||||
|
bench_traversal_test.go:715: ClosestNodes=2
|
||||||
|
bench_traversal_test.go:715: ClosestNodes=2
|
||||||
|
bench_traversal_test.go:715: ClosestNodes=2
|
||||||
|
bench_traversal_test.go:715: ClosestNodes=2
|
||||||
|
ok github.com/PuerkitoBio/goquery 224.003s
|
478
Godeps/_workspace/src/github.com/PuerkitoBio/goquery/bench/v0.3.2-go1.2
generated
vendored
Normal file
478
Godeps/_workspace/src/github.com/PuerkitoBio/goquery/bench/v0.3.2-go1.2
generated
vendored
Normal file
|
@ -0,0 +1,478 @@
|
||||||
|
PASS
|
||||||
|
BenchmarkFirst 20000000 88.4 ns/op
|
||||||
|
BenchmarkLast 20000000 88.2 ns/op
|
||||||
|
BenchmarkEq 20000000 87.4 ns/op
|
||||||
|
BenchmarkSlice 20000000 84.9 ns/op
|
||||||
|
BenchmarkGet 2000000000 1.99 ns/op
|
||||||
|
BenchmarkIndex 2000000 906 ns/op
|
||||||
|
--- BENCH: BenchmarkIndex
|
||||||
|
bench_array_test.go:73: Index=3
|
||||||
|
bench_array_test.go:73: Index=3
|
||||||
|
bench_array_test.go:73: Index=3
|
||||||
|
bench_array_test.go:73: Index=3
|
||||||
|
bench_array_test.go:73: Index=3
|
||||||
|
BenchmarkIndexSelector 100000 22276 ns/op
|
||||||
|
--- BENCH: BenchmarkIndexSelector
|
||||||
|
bench_array_test.go:85: IndexSelector=4
|
||||||
|
bench_array_test.go:85: IndexSelector=4
|
||||||
|
bench_array_test.go:85: IndexSelector=4
|
||||||
|
bench_array_test.go:85: IndexSelector=4
|
||||||
|
BenchmarkIndexOfNode 200000000 9.72 ns/op
|
||||||
|
--- BENCH: BenchmarkIndexOfNode
|
||||||
|
bench_array_test.go:99: IndexOfNode=2
|
||||||
|
bench_array_test.go:99: IndexOfNode=2
|
||||||
|
bench_array_test.go:99: IndexOfNode=2
|
||||||
|
bench_array_test.go:99: IndexOfNode=2
|
||||||
|
bench_array_test.go:99: IndexOfNode=2
|
||||||
|
bench_array_test.go:99: IndexOfNode=2
|
||||||
|
BenchmarkIndexOfSelection 100000000 10.4 ns/op
|
||||||
|
--- BENCH: BenchmarkIndexOfSelection
|
||||||
|
bench_array_test.go:111: IndexOfSelection=2
|
||||||
|
bench_array_test.go:111: IndexOfSelection=2
|
||||||
|
bench_array_test.go:111: IndexOfSelection=2
|
||||||
|
bench_array_test.go:111: IndexOfSelection=2
|
||||||
|
bench_array_test.go:111: IndexOfSelection=2
|
||||||
|
BenchmarkMetalReviewExample 10000 199277 ns/op
|
||||||
|
--- BENCH: BenchmarkMetalReviewExample
|
||||||
|
bench_example_test.go:40: Review 0: Midnight - Complete and Total Hell (8.5).
|
||||||
|
Review 1: Over Your Threshold - Facticity (6.0).
|
||||||
|
Review 2: Nuclear Death Terror - Chaos Reigns (7.5).
|
||||||
|
Review 3: Evoken - Atra Mors (9.5).
|
||||||
|
|
||||||
|
bench_example_test.go:41: MetalReviewExample=10
|
||||||
|
bench_example_test.go:40: Review 0: Midnight - Complete and Total Hell (8.5).
|
||||||
|
Review 1: Over Your Threshold - Facticity (6.0).
|
||||||
|
Review 2: Nuclear Death Terror - Chaos Reigns (7.5).
|
||||||
|
Review 3: Evoken - Atra Mors (9.5).
|
||||||
|
... [output truncated]
|
||||||
|
BenchmarkAdd 100000 18277 ns/op
|
||||||
|
--- BENCH: BenchmarkAdd
|
||||||
|
bench_expand_test.go:20: Add=43
|
||||||
|
bench_expand_test.go:20: Add=43
|
||||||
|
bench_expand_test.go:20: Add=43
|
||||||
|
bench_expand_test.go:20: Add=43
|
||||||
|
BenchmarkAddSelection 10000000 200 ns/op
|
||||||
|
--- BENCH: BenchmarkAddSelection
|
||||||
|
bench_expand_test.go:37: AddSelection=43
|
||||||
|
bench_expand_test.go:37: AddSelection=43
|
||||||
|
bench_expand_test.go:37: AddSelection=43
|
||||||
|
bench_expand_test.go:37: AddSelection=43
|
||||||
|
bench_expand_test.go:37: AddSelection=43
|
||||||
|
BenchmarkAddNodes 10000000 189 ns/op
|
||||||
|
--- BENCH: BenchmarkAddNodes
|
||||||
|
bench_expand_test.go:55: AddNodes=43
|
||||||
|
bench_expand_test.go:55: AddNodes=43
|
||||||
|
bench_expand_test.go:55: AddNodes=43
|
||||||
|
bench_expand_test.go:55: AddNodes=43
|
||||||
|
bench_expand_test.go:55: AddNodes=43
|
||||||
|
BenchmarkAndSelf 1000000 2569 ns/op
|
||||||
|
--- BENCH: BenchmarkAndSelf
|
||||||
|
bench_expand_test.go:71: AndSelf=44
|
||||||
|
bench_expand_test.go:71: AndSelf=44
|
||||||
|
bench_expand_test.go:71: AndSelf=44
|
||||||
|
bench_expand_test.go:71: AndSelf=44
|
||||||
|
BenchmarkFilter 100000 25195 ns/op
|
||||||
|
--- BENCH: BenchmarkFilter
|
||||||
|
bench_filter_test.go:20: Filter=13
|
||||||
|
bench_filter_test.go:20: Filter=13
|
||||||
|
bench_filter_test.go:20: Filter=13
|
||||||
|
bench_filter_test.go:20: Filter=13
|
||||||
|
BenchmarkNot 100000 29003 ns/op
|
||||||
|
--- BENCH: BenchmarkNot
|
||||||
|
bench_filter_test.go:36: Not=371
|
||||||
|
bench_filter_test.go:36: Not=371
|
||||||
|
bench_filter_test.go:36: Not=371
|
||||||
|
bench_filter_test.go:36: Not=371
|
||||||
|
BenchmarkFilterFunction 50000 60690 ns/op
|
||||||
|
--- BENCH: BenchmarkFilterFunction
|
||||||
|
bench_filter_test.go:55: FilterFunction=112
|
||||||
|
bench_filter_test.go:55: FilterFunction=112
|
||||||
|
bench_filter_test.go:55: FilterFunction=112
|
||||||
|
bench_filter_test.go:55: FilterFunction=112
|
||||||
|
BenchmarkNotFunction 50000 66008 ns/op
|
||||||
|
--- BENCH: BenchmarkNotFunction
|
||||||
|
bench_filter_test.go:74: NotFunction=261
|
||||||
|
bench_filter_test.go:74: NotFunction=261
|
||||||
|
bench_filter_test.go:74: NotFunction=261
|
||||||
|
bench_filter_test.go:74: NotFunction=261
|
||||||
|
BenchmarkFilterNodes 50000 59723 ns/op
|
||||||
|
--- BENCH: BenchmarkFilterNodes
|
||||||
|
bench_filter_test.go:92: FilterNodes=2
|
||||||
|
bench_filter_test.go:92: FilterNodes=2
|
||||||
|
bench_filter_test.go:92: FilterNodes=2
|
||||||
|
bench_filter_test.go:92: FilterNodes=2
|
||||||
|
BenchmarkNotNodes 50000 72698 ns/op
|
||||||
|
--- BENCH: BenchmarkNotNodes
|
||||||
|
bench_filter_test.go:110: NotNodes=360
|
||||||
|
bench_filter_test.go:110: NotNodes=360
|
||||||
|
bench_filter_test.go:110: NotNodes=360
|
||||||
|
bench_filter_test.go:110: NotNodes=360
|
||||||
|
BenchmarkFilterSelection 50000 59598 ns/op
|
||||||
|
--- BENCH: BenchmarkFilterSelection
|
||||||
|
bench_filter_test.go:127: FilterSelection=2
|
||||||
|
bench_filter_test.go:127: FilterSelection=2
|
||||||
|
bench_filter_test.go:127: FilterSelection=2
|
||||||
|
bench_filter_test.go:127: FilterSelection=2
|
||||||
|
BenchmarkNotSelection 50000 72526 ns/op
|
||||||
|
--- BENCH: BenchmarkNotSelection
|
||||||
|
bench_filter_test.go:144: NotSelection=360
|
||||||
|
bench_filter_test.go:144: NotSelection=360
|
||||||
|
bench_filter_test.go:144: NotSelection=360
|
||||||
|
bench_filter_test.go:144: NotSelection=360
|
||||||
|
BenchmarkHas 5000 367076 ns/op
|
||||||
|
--- BENCH: BenchmarkHas
|
||||||
|
bench_filter_test.go:160: Has=13
|
||||||
|
bench_filter_test.go:160: Has=13
|
||||||
|
bench_filter_test.go:160: Has=13
|
||||||
|
BenchmarkHasNodes 10000 219710 ns/op
|
||||||
|
--- BENCH: BenchmarkHasNodes
|
||||||
|
bench_filter_test.go:178: HasNodes=15
|
||||||
|
bench_filter_test.go:178: HasNodes=15
|
||||||
|
bench_filter_test.go:178: HasNodes=15
|
||||||
|
BenchmarkHasSelection 10000 219105 ns/op
|
||||||
|
--- BENCH: BenchmarkHasSelection
|
||||||
|
bench_filter_test.go:195: HasSelection=15
|
||||||
|
bench_filter_test.go:195: HasSelection=15
|
||||||
|
bench_filter_test.go:195: HasSelection=15
|
||||||
|
BenchmarkEnd 500000000 4.58 ns/op
|
||||||
|
--- BENCH: BenchmarkEnd
|
||||||
|
bench_filter_test.go:211: End=373
|
||||||
|
bench_filter_test.go:211: End=373
|
||||||
|
bench_filter_test.go:211: End=373
|
||||||
|
bench_filter_test.go:211: End=373
|
||||||
|
bench_filter_test.go:211: End=373
|
||||||
|
bench_filter_test.go:211: End=373
|
||||||
|
BenchmarkEach 200000 8615 ns/op
|
||||||
|
--- BENCH: BenchmarkEach
|
||||||
|
bench_iteration_test.go:22: Each=59
|
||||||
|
bench_iteration_test.go:22: Each=59
|
||||||
|
bench_iteration_test.go:22: Each=59
|
||||||
|
bench_iteration_test.go:22: Each=59
|
||||||
|
BenchmarkMap 200000 14271 ns/op
|
||||||
|
--- BENCH: BenchmarkMap
|
||||||
|
bench_iteration_test.go:41: Map=59
|
||||||
|
bench_iteration_test.go:41: Map=59
|
||||||
|
bench_iteration_test.go:41: Map=59
|
||||||
|
bench_iteration_test.go:41: Map=59
|
||||||
|
BenchmarkEachWithBreak 1000000 1497 ns/op
|
||||||
|
--- BENCH: BenchmarkEachWithBreak
|
||||||
|
bench_iteration_test.go:61: Each=10
|
||||||
|
bench_iteration_test.go:61: Each=10
|
||||||
|
bench_iteration_test.go:61: Each=10
|
||||||
|
bench_iteration_test.go:61: Each=10
|
||||||
|
BenchmarkAttr 50000000 30.9 ns/op
|
||||||
|
--- BENCH: BenchmarkAttr
|
||||||
|
bench_property_test.go:16: Attr=firstHeading
|
||||||
|
bench_property_test.go:16: Attr=firstHeading
|
||||||
|
bench_property_test.go:16: Attr=firstHeading
|
||||||
|
bench_property_test.go:16: Attr=firstHeading
|
||||||
|
bench_property_test.go:16: Attr=firstHeading
|
||||||
|
BenchmarkText 200000 13729 ns/op
|
||||||
|
BenchmarkLength 2000000000 0.31 ns/op
|
||||||
|
--- BENCH: BenchmarkLength
|
||||||
|
bench_property_test.go:37: Length=14
|
||||||
|
bench_property_test.go:37: Length=14
|
||||||
|
bench_property_test.go:37: Length=14
|
||||||
|
bench_property_test.go:37: Length=14
|
||||||
|
bench_property_test.go:37: Length=14
|
||||||
|
bench_property_test.go:37: Length=14
|
||||||
|
BenchmarkHtml 5000000 537 ns/op
|
||||||
|
BenchmarkIs 100000 28904 ns/op
|
||||||
|
--- BENCH: BenchmarkIs
|
||||||
|
bench_query_test.go:16: Is=true
|
||||||
|
bench_query_test.go:16: Is=true
|
||||||
|
bench_query_test.go:16: Is=true
|
||||||
|
bench_query_test.go:16: Is=true
|
||||||
|
BenchmarkIsPositional 100000 23556 ns/op
|
||||||
|
--- BENCH: BenchmarkIsPositional
|
||||||
|
bench_query_test.go:28: IsPositional=true
|
||||||
|
bench_query_test.go:28: IsPositional=true
|
||||||
|
bench_query_test.go:28: IsPositional=true
|
||||||
|
bench_query_test.go:28: IsPositional=true
|
||||||
|
BenchmarkIsFunction 1000000 2195 ns/op
|
||||||
|
--- BENCH: BenchmarkIsFunction
|
||||||
|
bench_query_test.go:43: IsFunction=true
|
||||||
|
bench_query_test.go:43: IsFunction=true
|
||||||
|
bench_query_test.go:43: IsFunction=true
|
||||||
|
bench_query_test.go:43: IsFunction=true
|
||||||
|
BenchmarkIsSelection 50000 60100 ns/op
|
||||||
|
--- BENCH: BenchmarkIsSelection
|
||||||
|
bench_query_test.go:56: IsSelection=true
|
||||||
|
bench_query_test.go:56: IsSelection=true
|
||||||
|
bench_query_test.go:56: IsSelection=true
|
||||||
|
bench_query_test.go:56: IsSelection=true
|
||||||
|
BenchmarkIsNodes 50000 59962 ns/op
|
||||||
|
--- BENCH: BenchmarkIsNodes
|
||||||
|
bench_query_test.go:70: IsNodes=true
|
||||||
|
bench_query_test.go:70: IsNodes=true
|
||||||
|
bench_query_test.go:70: IsNodes=true
|
||||||
|
bench_query_test.go:70: IsNodes=true
|
||||||
|
BenchmarkHasClass 5000 388679 ns/op
|
||||||
|
--- BENCH: BenchmarkHasClass
|
||||||
|
bench_query_test.go:82: HasClass=true
|
||||||
|
bench_query_test.go:82: HasClass=true
|
||||||
|
bench_query_test.go:82: HasClass=true
|
||||||
|
BenchmarkContains 100000000 11.0 ns/op
|
||||||
|
--- BENCH: BenchmarkContains
|
||||||
|
bench_query_test.go:96: Contains=true
|
||||||
|
bench_query_test.go:96: Contains=true
|
||||||
|
bench_query_test.go:96: Contains=true
|
||||||
|
bench_query_test.go:96: Contains=true
|
||||||
|
bench_query_test.go:96: Contains=true
|
||||||
|
BenchmarkFind 100000 22779 ns/op
|
||||||
|
--- BENCH: BenchmarkFind
|
||||||
|
bench_traversal_test.go:18: Find=41
|
||||||
|
bench_traversal_test.go:18: Find=41
|
||||||
|
bench_traversal_test.go:18: Find=41
|
||||||
|
bench_traversal_test.go:18: Find=41
|
||||||
|
BenchmarkFindWithinSelection 50000 62033 ns/op
|
||||||
|
--- BENCH: BenchmarkFindWithinSelection
|
||||||
|
bench_traversal_test.go:34: FindWithinSelection=39
|
||||||
|
bench_traversal_test.go:34: FindWithinSelection=39
|
||||||
|
bench_traversal_test.go:34: FindWithinSelection=39
|
||||||
|
bench_traversal_test.go:34: FindWithinSelection=39
|
||||||
|
BenchmarkFindSelection 5000 446918 ns/op
|
||||||
|
--- BENCH: BenchmarkFindSelection
|
||||||
|
bench_traversal_test.go:51: FindSelection=73
|
||||||
|
bench_traversal_test.go:51: FindSelection=73
|
||||||
|
bench_traversal_test.go:51: FindSelection=73
|
||||||
|
BenchmarkFindNodes 5000 441753 ns/op
|
||||||
|
--- BENCH: BenchmarkFindNodes
|
||||||
|
bench_traversal_test.go:69: FindNodes=73
|
||||||
|
bench_traversal_test.go:69: FindNodes=73
|
||||||
|
bench_traversal_test.go:69: FindNodes=73
|
||||||
|
BenchmarkContents 1000000 2807 ns/op
|
||||||
|
--- BENCH: BenchmarkContents
|
||||||
|
bench_traversal_test.go:85: Contents=16
|
||||||
|
bench_traversal_test.go:85: Contents=16
|
||||||
|
bench_traversal_test.go:85: Contents=16
|
||||||
|
bench_traversal_test.go:85: Contents=16
|
||||||
|
BenchmarkContentsFiltered 500000 4477 ns/op
|
||||||
|
--- BENCH: BenchmarkContentsFiltered
|
||||||
|
bench_traversal_test.go:101: ContentsFiltered=1
|
||||||
|
bench_traversal_test.go:101: ContentsFiltered=1
|
||||||
|
bench_traversal_test.go:101: ContentsFiltered=1
|
||||||
|
bench_traversal_test.go:101: ContentsFiltered=1
|
||||||
|
BenchmarkChildren 5000000 548 ns/op
|
||||||
|
--- BENCH: BenchmarkChildren
|
||||||
|
bench_traversal_test.go:117: Children=2
|
||||||
|
bench_traversal_test.go:117: Children=2
|
||||||
|
bench_traversal_test.go:117: Children=2
|
||||||
|
bench_traversal_test.go:117: Children=2
|
||||||
|
bench_traversal_test.go:117: Children=2
|
||||||
|
BenchmarkChildrenFiltered 500000 3304 ns/op
|
||||||
|
--- BENCH: BenchmarkChildrenFiltered
|
||||||
|
bench_traversal_test.go:133: ChildrenFiltered=2
|
||||||
|
bench_traversal_test.go:133: ChildrenFiltered=2
|
||||||
|
bench_traversal_test.go:133: ChildrenFiltered=2
|
||||||
|
bench_traversal_test.go:133: ChildrenFiltered=2
|
||||||
|
BenchmarkParent 50000 38248 ns/op
|
||||||
|
--- BENCH: BenchmarkParent
|
||||||
|
bench_traversal_test.go:149: Parent=55
|
||||||
|
bench_traversal_test.go:149: Parent=55
|
||||||
|
bench_traversal_test.go:149: Parent=55
|
||||||
|
bench_traversal_test.go:149: Parent=55
|
||||||
|
BenchmarkParentFiltered 50000 40677 ns/op
|
||||||
|
--- BENCH: BenchmarkParentFiltered
|
||||||
|
bench_traversal_test.go:165: ParentFiltered=4
|
||||||
|
bench_traversal_test.go:165: ParentFiltered=4
|
||||||
|
bench_traversal_test.go:165: ParentFiltered=4
|
||||||
|
bench_traversal_test.go:165: ParentFiltered=4
|
||||||
|
BenchmarkParents 20000 83043 ns/op
|
||||||
|
--- BENCH: BenchmarkParents
|
||||||
|
bench_traversal_test.go:181: Parents=73
|
||||||
|
bench_traversal_test.go:181: Parents=73
|
||||||
|
bench_traversal_test.go:181: Parents=73
|
||||||
|
bench_traversal_test.go:181: Parents=73
|
||||||
|
BenchmarkParentsFiltered 20000 85391 ns/op
|
||||||
|
--- BENCH: BenchmarkParentsFiltered
|
||||||
|
bench_traversal_test.go:197: ParentsFiltered=18
|
||||||
|
bench_traversal_test.go:197: ParentsFiltered=18
|
||||||
|
bench_traversal_test.go:197: ParentsFiltered=18
|
||||||
|
bench_traversal_test.go:197: ParentsFiltered=18
|
||||||
|
BenchmarkParentsUntil 50000 65118 ns/op
|
||||||
|
--- BENCH: BenchmarkParentsUntil
|
||||||
|
bench_traversal_test.go:213: ParentsUntil=52
|
||||||
|
bench_traversal_test.go:213: ParentsUntil=52
|
||||||
|
bench_traversal_test.go:213: ParentsUntil=52
|
||||||
|
bench_traversal_test.go:213: ParentsUntil=52
|
||||||
|
BenchmarkParentsUntilSelection 10000 144028 ns/op
|
||||||
|
--- BENCH: BenchmarkParentsUntilSelection
|
||||||
|
bench_traversal_test.go:230: ParentsUntilSelection=70
|
||||||
|
bench_traversal_test.go:230: ParentsUntilSelection=70
|
||||||
|
bench_traversal_test.go:230: ParentsUntilSelection=70
|
||||||
|
BenchmarkParentsUntilNodes 10000 146713 ns/op
|
||||||
|
--- BENCH: BenchmarkParentsUntilNodes
|
||||||
|
bench_traversal_test.go:248: ParentsUntilNodes=70
|
||||||
|
bench_traversal_test.go:248: ParentsUntilNodes=70
|
||||||
|
bench_traversal_test.go:248: ParentsUntilNodes=70
|
||||||
|
BenchmarkParentsFilteredUntil 100000 15113 ns/op
|
||||||
|
--- BENCH: BenchmarkParentsFilteredUntil
|
||||||
|
bench_traversal_test.go:264: ParentsFilteredUntil=2
|
||||||
|
bench_traversal_test.go:264: ParentsFilteredUntil=2
|
||||||
|
bench_traversal_test.go:264: ParentsFilteredUntil=2
|
||||||
|
bench_traversal_test.go:264: ParentsFilteredUntil=2
|
||||||
|
BenchmarkParentsFilteredUntilSelection 100000 18881 ns/op
|
||||||
|
--- BENCH: BenchmarkParentsFilteredUntilSelection
|
||||||
|
bench_traversal_test.go:281: ParentsFilteredUntilSelection=2
|
||||||
|
bench_traversal_test.go:281: ParentsFilteredUntilSelection=2
|
||||||
|
bench_traversal_test.go:281: ParentsFilteredUntilSelection=2
|
||||||
|
bench_traversal_test.go:281: ParentsFilteredUntilSelection=2
|
||||||
|
BenchmarkParentsFilteredUntilNodes 100000 18926 ns/op
|
||||||
|
--- BENCH: BenchmarkParentsFilteredUntilNodes
|
||||||
|
bench_traversal_test.go:299: ParentsFilteredUntilNodes=2
|
||||||
|
bench_traversal_test.go:299: ParentsFilteredUntilNodes=2
|
||||||
|
bench_traversal_test.go:299: ParentsFilteredUntilNodes=2
|
||||||
|
bench_traversal_test.go:299: ParentsFilteredUntilNodes=2
|
||||||
|
BenchmarkSiblings 50000 63221 ns/op
|
||||||
|
--- BENCH: BenchmarkSiblings
|
||||||
|
bench_traversal_test.go:315: Siblings=293
|
||||||
|
bench_traversal_test.go:315: Siblings=293
|
||||||
|
bench_traversal_test.go:315: Siblings=293
|
||||||
|
bench_traversal_test.go:315: Siblings=293
|
||||||
|
BenchmarkSiblingsFiltered 50000 69028 ns/op
|
||||||
|
--- BENCH: BenchmarkSiblingsFiltered
|
||||||
|
bench_traversal_test.go:331: SiblingsFiltered=46
|
||||||
|
bench_traversal_test.go:331: SiblingsFiltered=46
|
||||||
|
bench_traversal_test.go:331: SiblingsFiltered=46
|
||||||
|
bench_traversal_test.go:331: SiblingsFiltered=46
|
||||||
|
BenchmarkNext 200000 9133 ns/op
|
||||||
|
--- BENCH: BenchmarkNext
|
||||||
|
bench_traversal_test.go:347: Next=49
|
||||||
|
bench_traversal_test.go:347: Next=49
|
||||||
|
bench_traversal_test.go:347: Next=49
|
||||||
|
bench_traversal_test.go:347: Next=49
|
||||||
|
BenchmarkNextFiltered 200000 10601 ns/op
|
||||||
|
--- BENCH: BenchmarkNextFiltered
|
||||||
|
bench_traversal_test.go:363: NextFiltered=6
|
||||||
|
bench_traversal_test.go:363: NextFiltered=6
|
||||||
|
bench_traversal_test.go:363: NextFiltered=6
|
||||||
|
bench_traversal_test.go:363: NextFiltered=6
|
||||||
|
BenchmarkNextAll 50000 43089 ns/op
|
||||||
|
--- BENCH: BenchmarkNextAll
|
||||||
|
bench_traversal_test.go:379: NextAll=234
|
||||||
|
bench_traversal_test.go:379: NextAll=234
|
||||||
|
bench_traversal_test.go:379: NextAll=234
|
||||||
|
bench_traversal_test.go:379: NextAll=234
|
||||||
|
BenchmarkNextAllFiltered 50000 47867 ns/op
|
||||||
|
--- BENCH: BenchmarkNextAllFiltered
|
||||||
|
bench_traversal_test.go:395: NextAllFiltered=33
|
||||||
|
bench_traversal_test.go:395: NextAllFiltered=33
|
||||||
|
bench_traversal_test.go:395: NextAllFiltered=33
|
||||||
|
bench_traversal_test.go:395: NextAllFiltered=33
|
||||||
|
BenchmarkPrev 200000 9104 ns/op
|
||||||
|
--- BENCH: BenchmarkPrev
|
||||||
|
bench_traversal_test.go:411: Prev=49
|
||||||
|
bench_traversal_test.go:411: Prev=49
|
||||||
|
bench_traversal_test.go:411: Prev=49
|
||||||
|
bench_traversal_test.go:411: Prev=49
|
||||||
|
BenchmarkPrevFiltered 200000 10579 ns/op
|
||||||
|
--- BENCH: BenchmarkPrevFiltered
|
||||||
|
bench_traversal_test.go:429: PrevFiltered=7
|
||||||
|
bench_traversal_test.go:429: PrevFiltered=7
|
||||||
|
bench_traversal_test.go:429: PrevFiltered=7
|
||||||
|
bench_traversal_test.go:429: PrevFiltered=7
|
||||||
|
BenchmarkPrevAll 100000 15185 ns/op
|
||||||
|
--- BENCH: BenchmarkPrevAll
|
||||||
|
bench_traversal_test.go:445: PrevAll=78
|
||||||
|
bench_traversal_test.go:445: PrevAll=78
|
||||||
|
bench_traversal_test.go:445: PrevAll=78
|
||||||
|
bench_traversal_test.go:445: PrevAll=78
|
||||||
|
BenchmarkPrevAllFiltered 100000 17108 ns/op
|
||||||
|
--- BENCH: BenchmarkPrevAllFiltered
|
||||||
|
bench_traversal_test.go:461: PrevAllFiltered=6
|
||||||
|
bench_traversal_test.go:461: PrevAllFiltered=6
|
||||||
|
bench_traversal_test.go:461: PrevAllFiltered=6
|
||||||
|
bench_traversal_test.go:461: PrevAllFiltered=6
|
||||||
|
BenchmarkNextUntil 20000 81087 ns/op
|
||||||
|
--- BENCH: BenchmarkNextUntil
|
||||||
|
bench_traversal_test.go:477: NextUntil=84
|
||||||
|
bench_traversal_test.go:477: NextUntil=84
|
||||||
|
bench_traversal_test.go:477: NextUntil=84
|
||||||
|
bench_traversal_test.go:477: NextUntil=84
|
||||||
|
BenchmarkNextUntilSelection 50000 55831 ns/op
|
||||||
|
--- BENCH: BenchmarkNextUntilSelection
|
||||||
|
bench_traversal_test.go:494: NextUntilSelection=42
|
||||||
|
bench_traversal_test.go:494: NextUntilSelection=42
|
||||||
|
bench_traversal_test.go:494: NextUntilSelection=42
|
||||||
|
bench_traversal_test.go:494: NextUntilSelection=42
|
||||||
|
BenchmarkNextUntilNodes 100000 23130 ns/op
|
||||||
|
--- BENCH: BenchmarkNextUntilNodes
|
||||||
|
bench_traversal_test.go:512: NextUntilNodes=12
|
||||||
|
bench_traversal_test.go:512: NextUntilNodes=12
|
||||||
|
bench_traversal_test.go:512: NextUntilNodes=12
|
||||||
|
bench_traversal_test.go:512: NextUntilNodes=12
|
||||||
|
BenchmarkPrevUntil 10000 204673 ns/op
|
||||||
|
--- BENCH: BenchmarkPrevUntil
|
||||||
|
bench_traversal_test.go:528: PrevUntil=238
|
||||||
|
bench_traversal_test.go:528: PrevUntil=238
|
||||||
|
bench_traversal_test.go:528: PrevUntil=238
|
||||||
|
BenchmarkPrevUntilSelection 50000 70965 ns/op
|
||||||
|
--- BENCH: BenchmarkPrevUntilSelection
|
||||||
|
bench_traversal_test.go:545: PrevUntilSelection=49
|
||||||
|
bench_traversal_test.go:545: PrevUntilSelection=49
|
||||||
|
bench_traversal_test.go:545: PrevUntilSelection=49
|
||||||
|
bench_traversal_test.go:545: PrevUntilSelection=49
|
||||||
|
BenchmarkPrevUntilNodes 100000 18591 ns/op
|
||||||
|
--- BENCH: BenchmarkPrevUntilNodes
|
||||||
|
bench_traversal_test.go:563: PrevUntilNodes=11
|
||||||
|
bench_traversal_test.go:563: PrevUntilNodes=11
|
||||||
|
bench_traversal_test.go:563: PrevUntilNodes=11
|
||||||
|
bench_traversal_test.go:563: PrevUntilNodes=11
|
||||||
|
BenchmarkNextFilteredUntil 50000 42004 ns/op
|
||||||
|
--- BENCH: BenchmarkNextFilteredUntil
|
||||||
|
bench_traversal_test.go:579: NextFilteredUntil=22
|
||||||
|
bench_traversal_test.go:579: NextFilteredUntil=22
|
||||||
|
bench_traversal_test.go:579: NextFilteredUntil=22
|
||||||
|
bench_traversal_test.go:579: NextFilteredUntil=22
|
||||||
|
BenchmarkNextFilteredUntilSelection 50000 61953 ns/op
|
||||||
|
--- BENCH: BenchmarkNextFilteredUntilSelection
|
||||||
|
bench_traversal_test.go:596: NextFilteredUntilSelection=22
|
||||||
|
bench_traversal_test.go:596: NextFilteredUntilSelection=22
|
||||||
|
bench_traversal_test.go:596: NextFilteredUntilSelection=22
|
||||||
|
bench_traversal_test.go:596: NextFilteredUntilSelection=22
|
||||||
|
BenchmarkNextFilteredUntilNodes 50000 62124 ns/op
|
||||||
|
--- BENCH: BenchmarkNextFilteredUntilNodes
|
||||||
|
bench_traversal_test.go:614: NextFilteredUntilNodes=22
|
||||||
|
bench_traversal_test.go:614: NextFilteredUntilNodes=22
|
||||||
|
bench_traversal_test.go:614: NextFilteredUntilNodes=22
|
||||||
|
bench_traversal_test.go:614: NextFilteredUntilNodes=22
|
||||||
|
BenchmarkPrevFilteredUntil 50000 42861 ns/op
|
||||||
|
--- BENCH: BenchmarkPrevFilteredUntil
|
||||||
|
bench_traversal_test.go:630: PrevFilteredUntil=20
|
||||||
|
bench_traversal_test.go:630: PrevFilteredUntil=20
|
||||||
|
bench_traversal_test.go:630: PrevFilteredUntil=20
|
||||||
|
bench_traversal_test.go:630: PrevFilteredUntil=20
|
||||||
|
BenchmarkPrevFilteredUntilSelection 50000 62451 ns/op
|
||||||
|
--- BENCH: BenchmarkPrevFilteredUntilSelection
|
||||||
|
bench_traversal_test.go:647: PrevFilteredUntilSelection=20
|
||||||
|
bench_traversal_test.go:647: PrevFilteredUntilSelection=20
|
||||||
|
bench_traversal_test.go:647: PrevFilteredUntilSelection=20
|
||||||
|
bench_traversal_test.go:647: PrevFilteredUntilSelection=20
|
||||||
|
BenchmarkPrevFilteredUntilNodes 50000 62631 ns/op
|
||||||
|
--- BENCH: BenchmarkPrevFilteredUntilNodes
|
||||||
|
bench_traversal_test.go:665: PrevFilteredUntilNodes=20
|
||||||
|
bench_traversal_test.go:665: PrevFilteredUntilNodes=20
|
||||||
|
bench_traversal_test.go:665: PrevFilteredUntilNodes=20
|
||||||
|
bench_traversal_test.go:665: PrevFilteredUntilNodes=20
|
||||||
|
BenchmarkClosest 500000 4684 ns/op
|
||||||
|
--- BENCH: BenchmarkClosest
|
||||||
|
bench_traversal_test.go:681: Closest=2
|
||||||
|
bench_traversal_test.go:681: Closest=2
|
||||||
|
bench_traversal_test.go:681: Closest=2
|
||||||
|
bench_traversal_test.go:681: Closest=2
|
||||||
|
BenchmarkClosestSelection 5000000 622 ns/op
|
||||||
|
--- BENCH: BenchmarkClosestSelection
|
||||||
|
bench_traversal_test.go:698: ClosestSelection=2
|
||||||
|
bench_traversal_test.go:698: ClosestSelection=2
|
||||||
|
bench_traversal_test.go:698: ClosestSelection=2
|
||||||
|
bench_traversal_test.go:698: ClosestSelection=2
|
||||||
|
bench_traversal_test.go:698: ClosestSelection=2
|
||||||
|
BenchmarkClosestNodes 5000000 617 ns/op
|
||||||
|
--- BENCH: BenchmarkClosestNodes
|
||||||
|
bench_traversal_test.go:715: ClosestNodes=2
|
||||||
|
bench_traversal_test.go:715: ClosestNodes=2
|
||||||
|
bench_traversal_test.go:715: ClosestNodes=2
|
||||||
|
bench_traversal_test.go:715: ClosestNodes=2
|
||||||
|
bench_traversal_test.go:715: ClosestNodes=2
|
||||||
|
ok github.com/PuerkitoBio/goquery 218.724s
|
477
Godeps/_workspace/src/github.com/PuerkitoBio/goquery/bench/v0.3.2-go1.2-take2
generated
vendored
Normal file
477
Godeps/_workspace/src/github.com/PuerkitoBio/goquery/bench/v0.3.2-go1.2-take2
generated
vendored
Normal file
|
@ -0,0 +1,477 @@
|
||||||
|
PASS
|
||||||
|
BenchmarkFirst 20000000 88.3 ns/op
|
||||||
|
BenchmarkLast 20000000 88.9 ns/op
|
||||||
|
BenchmarkEq 20000000 86.7 ns/op
|
||||||
|
BenchmarkSlice 20000000 84.1 ns/op
|
||||||
|
BenchmarkGet 2000000000 1.99 ns/op
|
||||||
|
BenchmarkIndex 2000000 907 ns/op
|
||||||
|
--- BENCH: BenchmarkIndex
|
||||||
|
bench_array_test.go:73: Index=3
|
||||||
|
bench_array_test.go:73: Index=3
|
||||||
|
bench_array_test.go:73: Index=3
|
||||||
|
bench_array_test.go:73: Index=3
|
||||||
|
bench_array_test.go:73: Index=3
|
||||||
|
BenchmarkIndexSelector 200000 13052 ns/op
|
||||||
|
--- BENCH: BenchmarkIndexSelector
|
||||||
|
bench_array_test.go:85: IndexSelector=4
|
||||||
|
bench_array_test.go:85: IndexSelector=4
|
||||||
|
bench_array_test.go:85: IndexSelector=4
|
||||||
|
bench_array_test.go:85: IndexSelector=4
|
||||||
|
BenchmarkIndexOfNode 100000000 10.5 ns/op
|
||||||
|
--- BENCH: BenchmarkIndexOfNode
|
||||||
|
bench_array_test.go:99: IndexOfNode=2
|
||||||
|
bench_array_test.go:99: IndexOfNode=2
|
||||||
|
bench_array_test.go:99: IndexOfNode=2
|
||||||
|
bench_array_test.go:99: IndexOfNode=2
|
||||||
|
bench_array_test.go:99: IndexOfNode=2
|
||||||
|
BenchmarkIndexOfSelection 100000000 11.6 ns/op
|
||||||
|
--- BENCH: BenchmarkIndexOfSelection
|
||||||
|
bench_array_test.go:111: IndexOfSelection=2
|
||||||
|
bench_array_test.go:111: IndexOfSelection=2
|
||||||
|
bench_array_test.go:111: IndexOfSelection=2
|
||||||
|
bench_array_test.go:111: IndexOfSelection=2
|
||||||
|
bench_array_test.go:111: IndexOfSelection=2
|
||||||
|
BenchmarkMetalReviewExample 10000 189556 ns/op
|
||||||
|
--- BENCH: BenchmarkMetalReviewExample
|
||||||
|
bench_example_test.go:40: Review 0: Midnight - Complete and Total Hell (8.5).
|
||||||
|
Review 1: Over Your Threshold - Facticity (6.0).
|
||||||
|
Review 2: Nuclear Death Terror - Chaos Reigns (7.5).
|
||||||
|
Review 3: Evoken - Atra Mors (9.5).
|
||||||
|
|
||||||
|
bench_example_test.go:41: MetalReviewExample=10
|
||||||
|
bench_example_test.go:40: Review 0: Midnight - Complete and Total Hell (8.5).
|
||||||
|
Review 1: Over Your Threshold - Facticity (6.0).
|
||||||
|
Review 2: Nuclear Death Terror - Chaos Reigns (7.5).
|
||||||
|
Review 3: Evoken - Atra Mors (9.5).
|
||||||
|
... [output truncated]
|
||||||
|
BenchmarkAdd 200000 13714 ns/op
|
||||||
|
--- BENCH: BenchmarkAdd
|
||||||
|
bench_expand_test.go:20: Add=43
|
||||||
|
bench_expand_test.go:20: Add=43
|
||||||
|
bench_expand_test.go:20: Add=43
|
||||||
|
bench_expand_test.go:20: Add=43
|
||||||
|
BenchmarkAddSelection 10000000 200 ns/op
|
||||||
|
--- BENCH: BenchmarkAddSelection
|
||||||
|
bench_expand_test.go:37: AddSelection=43
|
||||||
|
bench_expand_test.go:37: AddSelection=43
|
||||||
|
bench_expand_test.go:37: AddSelection=43
|
||||||
|
bench_expand_test.go:37: AddSelection=43
|
||||||
|
bench_expand_test.go:37: AddSelection=43
|
||||||
|
BenchmarkAddNodes 10000000 186 ns/op
|
||||||
|
--- BENCH: BenchmarkAddNodes
|
||||||
|
bench_expand_test.go:55: AddNodes=43
|
||||||
|
bench_expand_test.go:55: AddNodes=43
|
||||||
|
bench_expand_test.go:55: AddNodes=43
|
||||||
|
bench_expand_test.go:55: AddNodes=43
|
||||||
|
bench_expand_test.go:55: AddNodes=43
|
||||||
|
BenchmarkAndSelf 1000000 2532 ns/op
|
||||||
|
--- BENCH: BenchmarkAndSelf
|
||||||
|
bench_expand_test.go:71: AndSelf=44
|
||||||
|
bench_expand_test.go:71: AndSelf=44
|
||||||
|
bench_expand_test.go:71: AndSelf=44
|
||||||
|
bench_expand_test.go:71: AndSelf=44
|
||||||
|
BenchmarkFilter 100000 25199 ns/op
|
||||||
|
--- BENCH: BenchmarkFilter
|
||||||
|
bench_filter_test.go:20: Filter=13
|
||||||
|
bench_filter_test.go:20: Filter=13
|
||||||
|
bench_filter_test.go:20: Filter=13
|
||||||
|
bench_filter_test.go:20: Filter=13
|
||||||
|
BenchmarkNot 100000 29162 ns/op
|
||||||
|
--- BENCH: BenchmarkNot
|
||||||
|
bench_filter_test.go:36: Not=371
|
||||||
|
bench_filter_test.go:36: Not=371
|
||||||
|
bench_filter_test.go:36: Not=371
|
||||||
|
bench_filter_test.go:36: Not=371
|
||||||
|
BenchmarkFilterFunction 50000 60733 ns/op
|
||||||
|
--- BENCH: BenchmarkFilterFunction
|
||||||
|
bench_filter_test.go:55: FilterFunction=112
|
||||||
|
bench_filter_test.go:55: FilterFunction=112
|
||||||
|
bench_filter_test.go:55: FilterFunction=112
|
||||||
|
bench_filter_test.go:55: FilterFunction=112
|
||||||
|
BenchmarkNotFunction 50000 66124 ns/op
|
||||||
|
--- BENCH: BenchmarkNotFunction
|
||||||
|
bench_filter_test.go:74: NotFunction=261
|
||||||
|
bench_filter_test.go:74: NotFunction=261
|
||||||
|
bench_filter_test.go:74: NotFunction=261
|
||||||
|
bench_filter_test.go:74: NotFunction=261
|
||||||
|
BenchmarkFilterNodes 50000 59489 ns/op
|
||||||
|
--- BENCH: BenchmarkFilterNodes
|
||||||
|
bench_filter_test.go:92: FilterNodes=2
|
||||||
|
bench_filter_test.go:92: FilterNodes=2
|
||||||
|
bench_filter_test.go:92: FilterNodes=2
|
||||||
|
bench_filter_test.go:92: FilterNodes=2
|
||||||
|
BenchmarkNotNodes 50000 73623 ns/op
|
||||||
|
--- BENCH: BenchmarkNotNodes
|
||||||
|
bench_filter_test.go:110: NotNodes=360
|
||||||
|
bench_filter_test.go:110: NotNodes=360
|
||||||
|
bench_filter_test.go:110: NotNodes=360
|
||||||
|
bench_filter_test.go:110: NotNodes=360
|
||||||
|
BenchmarkFilterSelection 50000 60053 ns/op
|
||||||
|
--- BENCH: BenchmarkFilterSelection
|
||||||
|
bench_filter_test.go:127: FilterSelection=2
|
||||||
|
bench_filter_test.go:127: FilterSelection=2
|
||||||
|
bench_filter_test.go:127: FilterSelection=2
|
||||||
|
bench_filter_test.go:127: FilterSelection=2
|
||||||
|
BenchmarkNotSelection 50000 73477 ns/op
|
||||||
|
--- BENCH: BenchmarkNotSelection
|
||||||
|
bench_filter_test.go:144: NotSelection=360
|
||||||
|
bench_filter_test.go:144: NotSelection=360
|
||||||
|
bench_filter_test.go:144: NotSelection=360
|
||||||
|
bench_filter_test.go:144: NotSelection=360
|
||||||
|
BenchmarkHas 5000 364859 ns/op
|
||||||
|
--- BENCH: BenchmarkHas
|
||||||
|
bench_filter_test.go:160: Has=13
|
||||||
|
bench_filter_test.go:160: Has=13
|
||||||
|
bench_filter_test.go:160: Has=13
|
||||||
|
BenchmarkHasNodes 10000 226980 ns/op
|
||||||
|
--- BENCH: BenchmarkHasNodes
|
||||||
|
bench_filter_test.go:178: HasNodes=15
|
||||||
|
bench_filter_test.go:178: HasNodes=15
|
||||||
|
bench_filter_test.go:178: HasNodes=15
|
||||||
|
BenchmarkHasSelection 10000 220471 ns/op
|
||||||
|
--- BENCH: BenchmarkHasSelection
|
||||||
|
bench_filter_test.go:195: HasSelection=15
|
||||||
|
bench_filter_test.go:195: HasSelection=15
|
||||||
|
bench_filter_test.go:195: HasSelection=15
|
||||||
|
BenchmarkEnd 500000000 4.64 ns/op
|
||||||
|
--- BENCH: BenchmarkEnd
|
||||||
|
bench_filter_test.go:211: End=373
|
||||||
|
bench_filter_test.go:211: End=373
|
||||||
|
bench_filter_test.go:211: End=373
|
||||||
|
bench_filter_test.go:211: End=373
|
||||||
|
bench_filter_test.go:211: End=373
|
||||||
|
bench_filter_test.go:211: End=373
|
||||||
|
BenchmarkEach 200000 8811 ns/op
|
||||||
|
--- BENCH: BenchmarkEach
|
||||||
|
bench_iteration_test.go:22: Each=59
|
||||||
|
bench_iteration_test.go:22: Each=59
|
||||||
|
bench_iteration_test.go:22: Each=59
|
||||||
|
bench_iteration_test.go:22: Each=59
|
||||||
|
BenchmarkMap 100000 15365 ns/op
|
||||||
|
--- BENCH: BenchmarkMap
|
||||||
|
bench_iteration_test.go:41: Map=59
|
||||||
|
bench_iteration_test.go:41: Map=59
|
||||||
|
bench_iteration_test.go:41: Map=59
|
||||||
|
bench_iteration_test.go:41: Map=59
|
||||||
|
BenchmarkEachWithBreak 1000000 1559 ns/op
|
||||||
|
--- BENCH: BenchmarkEachWithBreak
|
||||||
|
bench_iteration_test.go:61: Each=10
|
||||||
|
bench_iteration_test.go:61: Each=10
|
||||||
|
bench_iteration_test.go:61: Each=10
|
||||||
|
bench_iteration_test.go:61: Each=10
|
||||||
|
BenchmarkAttr 50000000 31.7 ns/op
|
||||||
|
--- BENCH: BenchmarkAttr
|
||||||
|
bench_property_test.go:16: Attr=firstHeading
|
||||||
|
bench_property_test.go:16: Attr=firstHeading
|
||||||
|
bench_property_test.go:16: Attr=firstHeading
|
||||||
|
bench_property_test.go:16: Attr=firstHeading
|
||||||
|
bench_property_test.go:16: Attr=firstHeading
|
||||||
|
BenchmarkText 200000 13901 ns/op
|
||||||
|
BenchmarkLength 2000000000 0.31 ns/op
|
||||||
|
--- BENCH: BenchmarkLength
|
||||||
|
bench_property_test.go:37: Length=14
|
||||||
|
bench_property_test.go:37: Length=14
|
||||||
|
bench_property_test.go:37: Length=14
|
||||||
|
bench_property_test.go:37: Length=14
|
||||||
|
bench_property_test.go:37: Length=14
|
||||||
|
bench_property_test.go:37: Length=14
|
||||||
|
BenchmarkHtml 5000000 541 ns/op
|
||||||
|
BenchmarkIs 100000 29435 ns/op
|
||||||
|
--- BENCH: BenchmarkIs
|
||||||
|
bench_query_test.go:16: Is=true
|
||||||
|
bench_query_test.go:16: Is=true
|
||||||
|
bench_query_test.go:16: Is=true
|
||||||
|
bench_query_test.go:16: Is=true
|
||||||
|
BenchmarkIsPositional 100000 22938 ns/op
|
||||||
|
--- BENCH: BenchmarkIsPositional
|
||||||
|
bench_query_test.go:28: IsPositional=true
|
||||||
|
bench_query_test.go:28: IsPositional=true
|
||||||
|
bench_query_test.go:28: IsPositional=true
|
||||||
|
bench_query_test.go:28: IsPositional=true
|
||||||
|
BenchmarkIsFunction 1000000 2185 ns/op
|
||||||
|
--- BENCH: BenchmarkIsFunction
|
||||||
|
bench_query_test.go:43: IsFunction=true
|
||||||
|
bench_query_test.go:43: IsFunction=true
|
||||||
|
bench_query_test.go:43: IsFunction=true
|
||||||
|
bench_query_test.go:43: IsFunction=true
|
||||||
|
BenchmarkIsSelection 50000 60607 ns/op
|
||||||
|
--- BENCH: BenchmarkIsSelection
|
||||||
|
bench_query_test.go:56: IsSelection=true
|
||||||
|
bench_query_test.go:56: IsSelection=true
|
||||||
|
bench_query_test.go:56: IsSelection=true
|
||||||
|
bench_query_test.go:56: IsSelection=true
|
||||||
|
BenchmarkIsNodes 50000 61599 ns/op
|
||||||
|
--- BENCH: BenchmarkIsNodes
|
||||||
|
bench_query_test.go:70: IsNodes=true
|
||||||
|
bench_query_test.go:70: IsNodes=true
|
||||||
|
bench_query_test.go:70: IsNodes=true
|
||||||
|
bench_query_test.go:70: IsNodes=true
|
||||||
|
BenchmarkHasClass 5000 395436 ns/op
|
||||||
|
--- BENCH: BenchmarkHasClass
|
||||||
|
bench_query_test.go:82: HasClass=true
|
||||||
|
bench_query_test.go:82: HasClass=true
|
||||||
|
bench_query_test.go:82: HasClass=true
|
||||||
|
BenchmarkContains 100000000 11.0 ns/op
|
||||||
|
--- BENCH: BenchmarkContains
|
||||||
|
bench_query_test.go:96: Contains=true
|
||||||
|
bench_query_test.go:96: Contains=true
|
||||||
|
bench_query_test.go:96: Contains=true
|
||||||
|
bench_query_test.go:96: Contains=true
|
||||||
|
bench_query_test.go:96: Contains=true
|
||||||
|
BenchmarkFind 200000 13788 ns/op
|
||||||
|
--- BENCH: BenchmarkFind
|
||||||
|
bench_traversal_test.go:18: Find=41
|
||||||
|
bench_traversal_test.go:18: Find=41
|
||||||
|
bench_traversal_test.go:18: Find=41
|
||||||
|
bench_traversal_test.go:18: Find=41
|
||||||
|
BenchmarkFindWithinSelection 50000 54253 ns/op
|
||||||
|
--- BENCH: BenchmarkFindWithinSelection
|
||||||
|
bench_traversal_test.go:34: FindWithinSelection=39
|
||||||
|
bench_traversal_test.go:34: FindWithinSelection=39
|
||||||
|
bench_traversal_test.go:34: FindWithinSelection=39
|
||||||
|
bench_traversal_test.go:34: FindWithinSelection=39
|
||||||
|
BenchmarkFindSelection 5000 438879 ns/op
|
||||||
|
--- BENCH: BenchmarkFindSelection
|
||||||
|
bench_traversal_test.go:51: FindSelection=73
|
||||||
|
bench_traversal_test.go:51: FindSelection=73
|
||||||
|
bench_traversal_test.go:51: FindSelection=73
|
||||||
|
BenchmarkFindNodes 5000 437225 ns/op
|
||||||
|
--- BENCH: BenchmarkFindNodes
|
||||||
|
bench_traversal_test.go:69: FindNodes=73
|
||||||
|
bench_traversal_test.go:69: FindNodes=73
|
||||||
|
bench_traversal_test.go:69: FindNodes=73
|
||||||
|
BenchmarkContents 1000000 2844 ns/op
|
||||||
|
--- BENCH: BenchmarkContents
|
||||||
|
bench_traversal_test.go:85: Contents=16
|
||||||
|
bench_traversal_test.go:85: Contents=16
|
||||||
|
bench_traversal_test.go:85: Contents=16
|
||||||
|
bench_traversal_test.go:85: Contents=16
|
||||||
|
BenchmarkContentsFiltered 500000 4528 ns/op
|
||||||
|
--- BENCH: BenchmarkContentsFiltered
|
||||||
|
bench_traversal_test.go:101: ContentsFiltered=1
|
||||||
|
bench_traversal_test.go:101: ContentsFiltered=1
|
||||||
|
bench_traversal_test.go:101: ContentsFiltered=1
|
||||||
|
bench_traversal_test.go:101: ContentsFiltered=1
|
||||||
|
BenchmarkChildren 5000000 552 ns/op
|
||||||
|
--- BENCH: BenchmarkChildren
|
||||||
|
bench_traversal_test.go:117: Children=2
|
||||||
|
bench_traversal_test.go:117: Children=2
|
||||||
|
bench_traversal_test.go:117: Children=2
|
||||||
|
bench_traversal_test.go:117: Children=2
|
||||||
|
bench_traversal_test.go:117: Children=2
|
||||||
|
BenchmarkChildrenFiltered 500000 3345 ns/op
|
||||||
|
--- BENCH: BenchmarkChildrenFiltered
|
||||||
|
bench_traversal_test.go:133: ChildrenFiltered=2
|
||||||
|
bench_traversal_test.go:133: ChildrenFiltered=2
|
||||||
|
bench_traversal_test.go:133: ChildrenFiltered=2
|
||||||
|
bench_traversal_test.go:133: ChildrenFiltered=2
|
||||||
|
BenchmarkParent 50000 39482 ns/op
|
||||||
|
--- BENCH: BenchmarkParent
|
||||||
|
bench_traversal_test.go:149: Parent=55
|
||||||
|
bench_traversal_test.go:149: Parent=55
|
||||||
|
bench_traversal_test.go:149: Parent=55
|
||||||
|
bench_traversal_test.go:149: Parent=55
|
||||||
|
BenchmarkParentFiltered 50000 42113 ns/op
|
||||||
|
--- BENCH: BenchmarkParentFiltered
|
||||||
|
bench_traversal_test.go:165: ParentFiltered=4
|
||||||
|
bench_traversal_test.go:165: ParentFiltered=4
|
||||||
|
bench_traversal_test.go:165: ParentFiltered=4
|
||||||
|
bench_traversal_test.go:165: ParentFiltered=4
|
||||||
|
BenchmarkParents 20000 84136 ns/op
|
||||||
|
--- BENCH: BenchmarkParents
|
||||||
|
bench_traversal_test.go:181: Parents=73
|
||||||
|
bench_traversal_test.go:181: Parents=73
|
||||||
|
bench_traversal_test.go:181: Parents=73
|
||||||
|
bench_traversal_test.go:181: Parents=73
|
||||||
|
BenchmarkParentsFiltered 20000 86041 ns/op
|
||||||
|
--- BENCH: BenchmarkParentsFiltered
|
||||||
|
bench_traversal_test.go:197: ParentsFiltered=18
|
||||||
|
bench_traversal_test.go:197: ParentsFiltered=18
|
||||||
|
bench_traversal_test.go:197: ParentsFiltered=18
|
||||||
|
bench_traversal_test.go:197: ParentsFiltered=18
|
||||||
|
BenchmarkParentsUntil 50000 65844 ns/op
|
||||||
|
--- BENCH: BenchmarkParentsUntil
|
||||||
|
bench_traversal_test.go:213: ParentsUntil=52
|
||||||
|
bench_traversal_test.go:213: ParentsUntil=52
|
||||||
|
bench_traversal_test.go:213: ParentsUntil=52
|
||||||
|
bench_traversal_test.go:213: ParentsUntil=52
|
||||||
|
BenchmarkParentsUntilSelection 10000 146903 ns/op
|
||||||
|
--- BENCH: BenchmarkParentsUntilSelection
|
||||||
|
bench_traversal_test.go:230: ParentsUntilSelection=70
|
||||||
|
bench_traversal_test.go:230: ParentsUntilSelection=70
|
||||||
|
bench_traversal_test.go:230: ParentsUntilSelection=70
|
||||||
|
BenchmarkParentsUntilNodes 10000 146638 ns/op
|
||||||
|
--- BENCH: BenchmarkParentsUntilNodes
|
||||||
|
bench_traversal_test.go:248: ParentsUntilNodes=70
|
||||||
|
bench_traversal_test.go:248: ParentsUntilNodes=70
|
||||||
|
bench_traversal_test.go:248: ParentsUntilNodes=70
|
||||||
|
BenchmarkParentsFilteredUntil 100000 16413 ns/op
|
||||||
|
--- BENCH: BenchmarkParentsFilteredUntil
|
||||||
|
bench_traversal_test.go:264: ParentsFilteredUntil=2
|
||||||
|
bench_traversal_test.go:264: ParentsFilteredUntil=2
|
||||||
|
bench_traversal_test.go:264: ParentsFilteredUntil=2
|
||||||
|
bench_traversal_test.go:264: ParentsFilteredUntil=2
|
||||||
|
BenchmarkParentsFilteredUntilSelection 100000 20366 ns/op
|
||||||
|
--- BENCH: BenchmarkParentsFilteredUntilSelection
|
||||||
|
bench_traversal_test.go:281: ParentsFilteredUntilSelection=2
|
||||||
|
bench_traversal_test.go:281: ParentsFilteredUntilSelection=2
|
||||||
|
bench_traversal_test.go:281: ParentsFilteredUntilSelection=2
|
||||||
|
bench_traversal_test.go:281: ParentsFilteredUntilSelection=2
|
||||||
|
BenchmarkParentsFilteredUntilNodes 100000 18800 ns/op
|
||||||
|
--- BENCH: BenchmarkParentsFilteredUntilNodes
|
||||||
|
bench_traversal_test.go:299: ParentsFilteredUntilNodes=2
|
||||||
|
bench_traversal_test.go:299: ParentsFilteredUntilNodes=2
|
||||||
|
bench_traversal_test.go:299: ParentsFilteredUntilNodes=2
|
||||||
|
bench_traversal_test.go:299: ParentsFilteredUntilNodes=2
|
||||||
|
BenchmarkSiblings 50000 63443 ns/op
|
||||||
|
--- BENCH: BenchmarkSiblings
|
||||||
|
bench_traversal_test.go:315: Siblings=293
|
||||||
|
bench_traversal_test.go:315: Siblings=293
|
||||||
|
bench_traversal_test.go:315: Siblings=293
|
||||||
|
bench_traversal_test.go:315: Siblings=293
|
||||||
|
BenchmarkSiblingsFiltered 50000 69250 ns/op
|
||||||
|
--- BENCH: BenchmarkSiblingsFiltered
|
||||||
|
bench_traversal_test.go:331: SiblingsFiltered=46
|
||||||
|
bench_traversal_test.go:331: SiblingsFiltered=46
|
||||||
|
bench_traversal_test.go:331: SiblingsFiltered=46
|
||||||
|
bench_traversal_test.go:331: SiblingsFiltered=46
|
||||||
|
BenchmarkNext 200000 9193 ns/op
|
||||||
|
--- BENCH: BenchmarkNext
|
||||||
|
bench_traversal_test.go:347: Next=49
|
||||||
|
bench_traversal_test.go:347: Next=49
|
||||||
|
bench_traversal_test.go:347: Next=49
|
||||||
|
bench_traversal_test.go:347: Next=49
|
||||||
|
BenchmarkNextFiltered 200000 10767 ns/op
|
||||||
|
--- BENCH: BenchmarkNextFiltered
|
||||||
|
bench_traversal_test.go:363: NextFiltered=6
|
||||||
|
bench_traversal_test.go:363: NextFiltered=6
|
||||||
|
bench_traversal_test.go:363: NextFiltered=6
|
||||||
|
bench_traversal_test.go:363: NextFiltered=6
|
||||||
|
BenchmarkNextAll 50000 42829 ns/op
|
||||||
|
--- BENCH: BenchmarkNextAll
|
||||||
|
bench_traversal_test.go:379: NextAll=234
|
||||||
|
bench_traversal_test.go:379: NextAll=234
|
||||||
|
bench_traversal_test.go:379: NextAll=234
|
||||||
|
bench_traversal_test.go:379: NextAll=234
|
||||||
|
BenchmarkNextAllFiltered 50000 48174 ns/op
|
||||||
|
--- BENCH: BenchmarkNextAllFiltered
|
||||||
|
bench_traversal_test.go:395: NextAllFiltered=33
|
||||||
|
bench_traversal_test.go:395: NextAllFiltered=33
|
||||||
|
bench_traversal_test.go:395: NextAllFiltered=33
|
||||||
|
bench_traversal_test.go:395: NextAllFiltered=33
|
||||||
|
BenchmarkPrev 200000 9114 ns/op
|
||||||
|
--- BENCH: BenchmarkPrev
|
||||||
|
bench_traversal_test.go:411: Prev=49
|
||||||
|
bench_traversal_test.go:411: Prev=49
|
||||||
|
bench_traversal_test.go:411: Prev=49
|
||||||
|
bench_traversal_test.go:411: Prev=49
|
||||||
|
BenchmarkPrevFiltered 200000 11114 ns/op
|
||||||
|
--- BENCH: BenchmarkPrevFiltered
|
||||||
|
bench_traversal_test.go:429: PrevFiltered=7
|
||||||
|
bench_traversal_test.go:429: PrevFiltered=7
|
||||||
|
bench_traversal_test.go:429: PrevFiltered=7
|
||||||
|
bench_traversal_test.go:429: PrevFiltered=7
|
||||||
|
BenchmarkPrevAll 100000 16387 ns/op
|
||||||
|
--- BENCH: BenchmarkPrevAll
|
||||||
|
bench_traversal_test.go:445: PrevAll=78
|
||||||
|
bench_traversal_test.go:445: PrevAll=78
|
||||||
|
bench_traversal_test.go:445: PrevAll=78
|
||||||
|
bench_traversal_test.go:445: PrevAll=78
|
||||||
|
BenchmarkPrevAllFiltered 100000 18322 ns/op
|
||||||
|
--- BENCH: BenchmarkPrevAllFiltered
|
||||||
|
bench_traversal_test.go:461: PrevAllFiltered=6
|
||||||
|
bench_traversal_test.go:461: PrevAllFiltered=6
|
||||||
|
bench_traversal_test.go:461: PrevAllFiltered=6
|
||||||
|
bench_traversal_test.go:461: PrevAllFiltered=6
|
||||||
|
BenchmarkNextUntil 20000 83828 ns/op
|
||||||
|
--- BENCH: BenchmarkNextUntil
|
||||||
|
bench_traversal_test.go:477: NextUntil=84
|
||||||
|
bench_traversal_test.go:477: NextUntil=84
|
||||||
|
bench_traversal_test.go:477: NextUntil=84
|
||||||
|
bench_traversal_test.go:477: NextUntil=84
|
||||||
|
BenchmarkNextUntilSelection 50000 58822 ns/op
|
||||||
|
--- BENCH: BenchmarkNextUntilSelection
|
||||||
|
bench_traversal_test.go:494: NextUntilSelection=42
|
||||||
|
bench_traversal_test.go:494: NextUntilSelection=42
|
||||||
|
bench_traversal_test.go:494: NextUntilSelection=42
|
||||||
|
bench_traversal_test.go:494: NextUntilSelection=42
|
||||||
|
BenchmarkNextUntilNodes 100000 23173 ns/op
|
||||||
|
--- BENCH: BenchmarkNextUntilNodes
|
||||||
|
bench_traversal_test.go:512: NextUntilNodes=12
|
||||||
|
bench_traversal_test.go:512: NextUntilNodes=12
|
||||||
|
bench_traversal_test.go:512: NextUntilNodes=12
|
||||||
|
bench_traversal_test.go:512: NextUntilNodes=12
|
||||||
|
BenchmarkPrevUntil 10000 219407 ns/op
|
||||||
|
--- BENCH: BenchmarkPrevUntil
|
||||||
|
bench_traversal_test.go:528: PrevUntil=238
|
||||||
|
bench_traversal_test.go:528: PrevUntil=238
|
||||||
|
bench_traversal_test.go:528: PrevUntil=238
|
||||||
|
BenchmarkPrevUntilSelection 20000 76033 ns/op
|
||||||
|
--- BENCH: BenchmarkPrevUntilSelection
|
||||||
|
bench_traversal_test.go:545: PrevUntilSelection=49
|
||||||
|
bench_traversal_test.go:545: PrevUntilSelection=49
|
||||||
|
bench_traversal_test.go:545: PrevUntilSelection=49
|
||||||
|
bench_traversal_test.go:545: PrevUntilSelection=49
|
||||||
|
BenchmarkPrevUntilNodes 100000 19417 ns/op
|
||||||
|
--- BENCH: BenchmarkPrevUntilNodes
|
||||||
|
bench_traversal_test.go:563: PrevUntilNodes=11
|
||||||
|
bench_traversal_test.go:563: PrevUntilNodes=11
|
||||||
|
bench_traversal_test.go:563: PrevUntilNodes=11
|
||||||
|
bench_traversal_test.go:563: PrevUntilNodes=11
|
||||||
|
BenchmarkNextFilteredUntil 50000 44648 ns/op
|
||||||
|
--- BENCH: BenchmarkNextFilteredUntil
|
||||||
|
bench_traversal_test.go:579: NextFilteredUntil=22
|
||||||
|
bench_traversal_test.go:579: NextFilteredUntil=22
|
||||||
|
bench_traversal_test.go:579: NextFilteredUntil=22
|
||||||
|
bench_traversal_test.go:579: NextFilteredUntil=22
|
||||||
|
BenchmarkNextFilteredUntilSelection 50000 62751 ns/op
|
||||||
|
--- BENCH: BenchmarkNextFilteredUntilSelection
|
||||||
|
bench_traversal_test.go:596: NextFilteredUntilSelection=22
|
||||||
|
bench_traversal_test.go:596: NextFilteredUntilSelection=22
|
||||||
|
bench_traversal_test.go:596: NextFilteredUntilSelection=22
|
||||||
|
bench_traversal_test.go:596: NextFilteredUntilSelection=22
|
||||||
|
BenchmarkNextFilteredUntilNodes 50000 62035 ns/op
|
||||||
|
--- BENCH: BenchmarkNextFilteredUntilNodes
|
||||||
|
bench_traversal_test.go:614: NextFilteredUntilNodes=22
|
||||||
|
bench_traversal_test.go:614: NextFilteredUntilNodes=22
|
||||||
|
bench_traversal_test.go:614: NextFilteredUntilNodes=22
|
||||||
|
bench_traversal_test.go:614: NextFilteredUntilNodes=22
|
||||||
|
BenchmarkPrevFilteredUntil 50000 43331 ns/op
|
||||||
|
--- BENCH: BenchmarkPrevFilteredUntil
|
||||||
|
bench_traversal_test.go:630: PrevFilteredUntil=20
|
||||||
|
bench_traversal_test.go:630: PrevFilteredUntil=20
|
||||||
|
bench_traversal_test.go:630: PrevFilteredUntil=20
|
||||||
|
bench_traversal_test.go:630: PrevFilteredUntil=20
|
||||||
|
BenchmarkPrevFilteredUntilSelection 50000 64767 ns/op
|
||||||
|
--- BENCH: BenchmarkPrevFilteredUntilSelection
|
||||||
|
bench_traversal_test.go:647: PrevFilteredUntilSelection=20
|
||||||
|
bench_traversal_test.go:647: PrevFilteredUntilSelection=20
|
||||||
|
bench_traversal_test.go:647: PrevFilteredUntilSelection=20
|
||||||
|
bench_traversal_test.go:647: PrevFilteredUntilSelection=20
|
||||||
|
BenchmarkPrevFilteredUntilNodes 50000 67808 ns/op
|
||||||
|
--- BENCH: BenchmarkPrevFilteredUntilNodes
|
||||||
|
bench_traversal_test.go:665: PrevFilteredUntilNodes=20
|
||||||
|
bench_traversal_test.go:665: PrevFilteredUntilNodes=20
|
||||||
|
bench_traversal_test.go:665: PrevFilteredUntilNodes=20
|
||||||
|
bench_traversal_test.go:665: PrevFilteredUntilNodes=20
|
||||||
|
BenchmarkClosest 500000 4870 ns/op
|
||||||
|
--- BENCH: BenchmarkClosest
|
||||||
|
bench_traversal_test.go:681: Closest=2
|
||||||
|
bench_traversal_test.go:681: Closest=2
|
||||||
|
bench_traversal_test.go:681: Closest=2
|
||||||
|
bench_traversal_test.go:681: Closest=2
|
||||||
|
BenchmarkClosestSelection 5000000 656 ns/op
|
||||||
|
--- BENCH: BenchmarkClosestSelection
|
||||||
|
bench_traversal_test.go:698: ClosestSelection=2
|
||||||
|
bench_traversal_test.go:698: ClosestSelection=2
|
||||||
|
bench_traversal_test.go:698: ClosestSelection=2
|
||||||
|
bench_traversal_test.go:698: ClosestSelection=2
|
||||||
|
bench_traversal_test.go:698: ClosestSelection=2
|
||||||
|
BenchmarkClosestNodes 5000000 663 ns/op
|
||||||
|
--- BENCH: BenchmarkClosestNodes
|
||||||
|
bench_traversal_test.go:715: ClosestNodes=2
|
||||||
|
bench_traversal_test.go:715: ClosestNodes=2
|
||||||
|
bench_traversal_test.go:715: ClosestNodes=2
|
||||||
|
bench_traversal_test.go:715: ClosestNodes=2
|
||||||
|
bench_traversal_test.go:715: ClosestNodes=2
|
||||||
|
ok github.com/PuerkitoBio/goquery 218.007s
|
477
Godeps/_workspace/src/github.com/PuerkitoBio/goquery/bench/v0.3.2-go1.2rc1
generated
vendored
Normal file
477
Godeps/_workspace/src/github.com/PuerkitoBio/goquery/bench/v0.3.2-go1.2rc1
generated
vendored
Normal file
|
@ -0,0 +1,477 @@
|
||||||
|
PASS
|
||||||
|
BenchmarkFirst 20000000 91.0 ns/op
|
||||||
|
BenchmarkLast 20000000 90.5 ns/op
|
||||||
|
BenchmarkEq 20000000 90.2 ns/op
|
||||||
|
BenchmarkSlice 20000000 88.0 ns/op
|
||||||
|
BenchmarkGet 1000000000 2.04 ns/op
|
||||||
|
BenchmarkIndex 2000000 935 ns/op
|
||||||
|
--- BENCH: BenchmarkIndex
|
||||||
|
bench_array_test.go:73: Index=3
|
||||||
|
bench_array_test.go:73: Index=3
|
||||||
|
bench_array_test.go:73: Index=3
|
||||||
|
bench_array_test.go:73: Index=3
|
||||||
|
bench_array_test.go:73: Index=3
|
||||||
|
BenchmarkIndexSelector 100000 23613 ns/op
|
||||||
|
--- BENCH: BenchmarkIndexSelector
|
||||||
|
bench_array_test.go:85: IndexSelector=4
|
||||||
|
bench_array_test.go:85: IndexSelector=4
|
||||||
|
bench_array_test.go:85: IndexSelector=4
|
||||||
|
bench_array_test.go:85: IndexSelector=4
|
||||||
|
BenchmarkIndexOfNode 100000000 10.2 ns/op
|
||||||
|
--- BENCH: BenchmarkIndexOfNode
|
||||||
|
bench_array_test.go:99: IndexOfNode=2
|
||||||
|
bench_array_test.go:99: IndexOfNode=2
|
||||||
|
bench_array_test.go:99: IndexOfNode=2
|
||||||
|
bench_array_test.go:99: IndexOfNode=2
|
||||||
|
bench_array_test.go:99: IndexOfNode=2
|
||||||
|
BenchmarkIndexOfSelection 100000000 11.0 ns/op
|
||||||
|
--- BENCH: BenchmarkIndexOfSelection
|
||||||
|
bench_array_test.go:111: IndexOfSelection=2
|
||||||
|
bench_array_test.go:111: IndexOfSelection=2
|
||||||
|
bench_array_test.go:111: IndexOfSelection=2
|
||||||
|
bench_array_test.go:111: IndexOfSelection=2
|
||||||
|
bench_array_test.go:111: IndexOfSelection=2
|
||||||
|
BenchmarkMetalReviewExample 10000 213843 ns/op
|
||||||
|
--- BENCH: BenchmarkMetalReviewExample
|
||||||
|
bench_example_test.go:40: Review 0: Midnight - Complete and Total Hell (8.5).
|
||||||
|
Review 1: Over Your Threshold - Facticity (6.0).
|
||||||
|
Review 2: Nuclear Death Terror - Chaos Reigns (7.5).
|
||||||
|
Review 3: Evoken - Atra Mors (9.5).
|
||||||
|
|
||||||
|
bench_example_test.go:41: MetalReviewExample=10
|
||||||
|
bench_example_test.go:40: Review 0: Midnight - Complete and Total Hell (8.5).
|
||||||
|
Review 1: Over Your Threshold - Facticity (6.0).
|
||||||
|
Review 2: Nuclear Death Terror - Chaos Reigns (7.5).
|
||||||
|
Review 3: Evoken - Atra Mors (9.5).
|
||||||
|
... [output truncated]
|
||||||
|
BenchmarkAdd 100000 18671 ns/op
|
||||||
|
--- BENCH: BenchmarkAdd
|
||||||
|
bench_expand_test.go:20: Add=43
|
||||||
|
bench_expand_test.go:20: Add=43
|
||||||
|
bench_expand_test.go:20: Add=43
|
||||||
|
bench_expand_test.go:20: Add=43
|
||||||
|
BenchmarkAddSelection 10000000 204 ns/op
|
||||||
|
--- BENCH: BenchmarkAddSelection
|
||||||
|
bench_expand_test.go:37: AddSelection=43
|
||||||
|
bench_expand_test.go:37: AddSelection=43
|
||||||
|
bench_expand_test.go:37: AddSelection=43
|
||||||
|
bench_expand_test.go:37: AddSelection=43
|
||||||
|
bench_expand_test.go:37: AddSelection=43
|
||||||
|
BenchmarkAddNodes 10000000 195 ns/op
|
||||||
|
--- BENCH: BenchmarkAddNodes
|
||||||
|
bench_expand_test.go:55: AddNodes=43
|
||||||
|
bench_expand_test.go:55: AddNodes=43
|
||||||
|
bench_expand_test.go:55: AddNodes=43
|
||||||
|
bench_expand_test.go:55: AddNodes=43
|
||||||
|
bench_expand_test.go:55: AddNodes=43
|
||||||
|
BenchmarkAndSelf 1000000 2611 ns/op
|
||||||
|
--- BENCH: BenchmarkAndSelf
|
||||||
|
bench_expand_test.go:71: AndSelf=44
|
||||||
|
bench_expand_test.go:71: AndSelf=44
|
||||||
|
bench_expand_test.go:71: AndSelf=44
|
||||||
|
bench_expand_test.go:71: AndSelf=44
|
||||||
|
BenchmarkFilter 100000 27571 ns/op
|
||||||
|
--- BENCH: BenchmarkFilter
|
||||||
|
bench_filter_test.go:20: Filter=13
|
||||||
|
bench_filter_test.go:20: Filter=13
|
||||||
|
bench_filter_test.go:20: Filter=13
|
||||||
|
bench_filter_test.go:20: Filter=13
|
||||||
|
BenchmarkNot 50000 32006 ns/op
|
||||||
|
--- BENCH: BenchmarkNot
|
||||||
|
bench_filter_test.go:36: Not=371
|
||||||
|
bench_filter_test.go:36: Not=371
|
||||||
|
bench_filter_test.go:36: Not=371
|
||||||
|
bench_filter_test.go:36: Not=371
|
||||||
|
BenchmarkFilterFunction 50000 61388 ns/op
|
||||||
|
--- BENCH: BenchmarkFilterFunction
|
||||||
|
bench_filter_test.go:55: FilterFunction=112
|
||||||
|
bench_filter_test.go:55: FilterFunction=112
|
||||||
|
bench_filter_test.go:55: FilterFunction=112
|
||||||
|
bench_filter_test.go:55: FilterFunction=112
|
||||||
|
BenchmarkNotFunction 50000 66702 ns/op
|
||||||
|
--- BENCH: BenchmarkNotFunction
|
||||||
|
bench_filter_test.go:74: NotFunction=261
|
||||||
|
bench_filter_test.go:74: NotFunction=261
|
||||||
|
bench_filter_test.go:74: NotFunction=261
|
||||||
|
bench_filter_test.go:74: NotFunction=261
|
||||||
|
BenchmarkFilterNodes 50000 59699 ns/op
|
||||||
|
--- BENCH: BenchmarkFilterNodes
|
||||||
|
bench_filter_test.go:92: FilterNodes=2
|
||||||
|
bench_filter_test.go:92: FilterNodes=2
|
||||||
|
bench_filter_test.go:92: FilterNodes=2
|
||||||
|
bench_filter_test.go:92: FilterNodes=2
|
||||||
|
BenchmarkNotNodes 50000 73248 ns/op
|
||||||
|
--- BENCH: BenchmarkNotNodes
|
||||||
|
bench_filter_test.go:110: NotNodes=360
|
||||||
|
bench_filter_test.go:110: NotNodes=360
|
||||||
|
bench_filter_test.go:110: NotNodes=360
|
||||||
|
bench_filter_test.go:110: NotNodes=360
|
||||||
|
BenchmarkFilterSelection 50000 59242 ns/op
|
||||||
|
--- BENCH: BenchmarkFilterSelection
|
||||||
|
bench_filter_test.go:127: FilterSelection=2
|
||||||
|
bench_filter_test.go:127: FilterSelection=2
|
||||||
|
bench_filter_test.go:127: FilterSelection=2
|
||||||
|
bench_filter_test.go:127: FilterSelection=2
|
||||||
|
BenchmarkNotSelection 50000 73211 ns/op
|
||||||
|
--- BENCH: BenchmarkNotSelection
|
||||||
|
bench_filter_test.go:144: NotSelection=360
|
||||||
|
bench_filter_test.go:144: NotSelection=360
|
||||||
|
bench_filter_test.go:144: NotSelection=360
|
||||||
|
bench_filter_test.go:144: NotSelection=360
|
||||||
|
BenchmarkHas 5000 395087 ns/op
|
||||||
|
--- BENCH: BenchmarkHas
|
||||||
|
bench_filter_test.go:160: Has=13
|
||||||
|
bench_filter_test.go:160: Has=13
|
||||||
|
bench_filter_test.go:160: Has=13
|
||||||
|
BenchmarkHasNodes 10000 215849 ns/op
|
||||||
|
--- BENCH: BenchmarkHasNodes
|
||||||
|
bench_filter_test.go:178: HasNodes=15
|
||||||
|
bench_filter_test.go:178: HasNodes=15
|
||||||
|
bench_filter_test.go:178: HasNodes=15
|
||||||
|
BenchmarkHasSelection 10000 215612 ns/op
|
||||||
|
--- BENCH: BenchmarkHasSelection
|
||||||
|
bench_filter_test.go:195: HasSelection=15
|
||||||
|
bench_filter_test.go:195: HasSelection=15
|
||||||
|
bench_filter_test.go:195: HasSelection=15
|
||||||
|
BenchmarkEnd 500000000 4.59 ns/op
|
||||||
|
--- BENCH: BenchmarkEnd
|
||||||
|
bench_filter_test.go:211: End=373
|
||||||
|
bench_filter_test.go:211: End=373
|
||||||
|
bench_filter_test.go:211: End=373
|
||||||
|
bench_filter_test.go:211: End=373
|
||||||
|
bench_filter_test.go:211: End=373
|
||||||
|
bench_filter_test.go:211: End=373
|
||||||
|
BenchmarkEach 200000 8588 ns/op
|
||||||
|
--- BENCH: BenchmarkEach
|
||||||
|
bench_iteration_test.go:22: Each=59
|
||||||
|
bench_iteration_test.go:22: Each=59
|
||||||
|
bench_iteration_test.go:22: Each=59
|
||||||
|
bench_iteration_test.go:22: Each=59
|
||||||
|
BenchmarkMap 200000 14444 ns/op
|
||||||
|
--- BENCH: BenchmarkMap
|
||||||
|
bench_iteration_test.go:41: Map=59
|
||||||
|
bench_iteration_test.go:41: Map=59
|
||||||
|
bench_iteration_test.go:41: Map=59
|
||||||
|
bench_iteration_test.go:41: Map=59
|
||||||
|
BenchmarkEachWithBreak 1000000 1490 ns/op
|
||||||
|
--- BENCH: BenchmarkEachWithBreak
|
||||||
|
bench_iteration_test.go:61: Each=10
|
||||||
|
bench_iteration_test.go:61: Each=10
|
||||||
|
bench_iteration_test.go:61: Each=10
|
||||||
|
bench_iteration_test.go:61: Each=10
|
||||||
|
BenchmarkAttr 50000000 30.9 ns/op
|
||||||
|
--- BENCH: BenchmarkAttr
|
||||||
|
bench_property_test.go:16: Attr=firstHeading
|
||||||
|
bench_property_test.go:16: Attr=firstHeading
|
||||||
|
bench_property_test.go:16: Attr=firstHeading
|
||||||
|
bench_property_test.go:16: Attr=firstHeading
|
||||||
|
bench_property_test.go:16: Attr=firstHeading
|
||||||
|
BenchmarkText 200000 14017 ns/op
|
||||||
|
BenchmarkLength 2000000000 0.31 ns/op
|
||||||
|
--- BENCH: BenchmarkLength
|
||||||
|
bench_property_test.go:37: Length=14
|
||||||
|
bench_property_test.go:37: Length=14
|
||||||
|
bench_property_test.go:37: Length=14
|
||||||
|
bench_property_test.go:37: Length=14
|
||||||
|
bench_property_test.go:37: Length=14
|
||||||
|
bench_property_test.go:37: Length=14
|
||||||
|
BenchmarkHtml 5000000 577 ns/op
|
||||||
|
BenchmarkIs 50000 31936 ns/op
|
||||||
|
--- BENCH: BenchmarkIs
|
||||||
|
bench_query_test.go:16: Is=true
|
||||||
|
bench_query_test.go:16: Is=true
|
||||||
|
bench_query_test.go:16: Is=true
|
||||||
|
bench_query_test.go:16: Is=true
|
||||||
|
BenchmarkIsPositional 100000 23372 ns/op
|
||||||
|
--- BENCH: BenchmarkIsPositional
|
||||||
|
bench_query_test.go:28: IsPositional=true
|
||||||
|
bench_query_test.go:28: IsPositional=true
|
||||||
|
bench_query_test.go:28: IsPositional=true
|
||||||
|
bench_query_test.go:28: IsPositional=true
|
||||||
|
BenchmarkIsFunction 1000000 2170 ns/op
|
||||||
|
--- BENCH: BenchmarkIsFunction
|
||||||
|
bench_query_test.go:43: IsFunction=true
|
||||||
|
bench_query_test.go:43: IsFunction=true
|
||||||
|
bench_query_test.go:43: IsFunction=true
|
||||||
|
bench_query_test.go:43: IsFunction=true
|
||||||
|
BenchmarkIsSelection 50000 59814 ns/op
|
||||||
|
--- BENCH: BenchmarkIsSelection
|
||||||
|
bench_query_test.go:56: IsSelection=true
|
||||||
|
bench_query_test.go:56: IsSelection=true
|
||||||
|
bench_query_test.go:56: IsSelection=true
|
||||||
|
bench_query_test.go:56: IsSelection=true
|
||||||
|
BenchmarkIsNodes 50000 59629 ns/op
|
||||||
|
--- BENCH: BenchmarkIsNodes
|
||||||
|
bench_query_test.go:70: IsNodes=true
|
||||||
|
bench_query_test.go:70: IsNodes=true
|
||||||
|
bench_query_test.go:70: IsNodes=true
|
||||||
|
bench_query_test.go:70: IsNodes=true
|
||||||
|
BenchmarkHasClass 5000 384894 ns/op
|
||||||
|
--- BENCH: BenchmarkHasClass
|
||||||
|
bench_query_test.go:82: HasClass=true
|
||||||
|
bench_query_test.go:82: HasClass=true
|
||||||
|
bench_query_test.go:82: HasClass=true
|
||||||
|
BenchmarkContains 100000000 11.4 ns/op
|
||||||
|
--- BENCH: BenchmarkContains
|
||||||
|
bench_query_test.go:96: Contains=true
|
||||||
|
bench_query_test.go:96: Contains=true
|
||||||
|
bench_query_test.go:96: Contains=true
|
||||||
|
bench_query_test.go:96: Contains=true
|
||||||
|
bench_query_test.go:96: Contains=true
|
||||||
|
BenchmarkFind 100000 23545 ns/op
|
||||||
|
--- BENCH: BenchmarkFind
|
||||||
|
bench_traversal_test.go:18: Find=41
|
||||||
|
bench_traversal_test.go:18: Find=41
|
||||||
|
bench_traversal_test.go:18: Find=41
|
||||||
|
bench_traversal_test.go:18: Find=41
|
||||||
|
BenchmarkFindWithinSelection 50000 63775 ns/op
|
||||||
|
--- BENCH: BenchmarkFindWithinSelection
|
||||||
|
bench_traversal_test.go:34: FindWithinSelection=39
|
||||||
|
bench_traversal_test.go:34: FindWithinSelection=39
|
||||||
|
bench_traversal_test.go:34: FindWithinSelection=39
|
||||||
|
bench_traversal_test.go:34: FindWithinSelection=39
|
||||||
|
BenchmarkFindSelection 5000 441958 ns/op
|
||||||
|
--- BENCH: BenchmarkFindSelection
|
||||||
|
bench_traversal_test.go:51: FindSelection=73
|
||||||
|
bench_traversal_test.go:51: FindSelection=73
|
||||||
|
bench_traversal_test.go:51: FindSelection=73
|
||||||
|
BenchmarkFindNodes 5000 437717 ns/op
|
||||||
|
--- BENCH: BenchmarkFindNodes
|
||||||
|
bench_traversal_test.go:69: FindNodes=73
|
||||||
|
bench_traversal_test.go:69: FindNodes=73
|
||||||
|
bench_traversal_test.go:69: FindNodes=73
|
||||||
|
BenchmarkContents 1000000 2799 ns/op
|
||||||
|
--- BENCH: BenchmarkContents
|
||||||
|
bench_traversal_test.go:85: Contents=16
|
||||||
|
bench_traversal_test.go:85: Contents=16
|
||||||
|
bench_traversal_test.go:85: Contents=16
|
||||||
|
bench_traversal_test.go:85: Contents=16
|
||||||
|
BenchmarkContentsFiltered 500000 4489 ns/op
|
||||||
|
--- BENCH: BenchmarkContentsFiltered
|
||||||
|
bench_traversal_test.go:101: ContentsFiltered=1
|
||||||
|
bench_traversal_test.go:101: ContentsFiltered=1
|
||||||
|
bench_traversal_test.go:101: ContentsFiltered=1
|
||||||
|
bench_traversal_test.go:101: ContentsFiltered=1
|
||||||
|
BenchmarkChildren 5000000 546 ns/op
|
||||||
|
--- BENCH: BenchmarkChildren
|
||||||
|
bench_traversal_test.go:117: Children=2
|
||||||
|
bench_traversal_test.go:117: Children=2
|
||||||
|
bench_traversal_test.go:117: Children=2
|
||||||
|
bench_traversal_test.go:117: Children=2
|
||||||
|
bench_traversal_test.go:117: Children=2
|
||||||
|
BenchmarkChildrenFiltered 500000 3472 ns/op
|
||||||
|
--- BENCH: BenchmarkChildrenFiltered
|
||||||
|
bench_traversal_test.go:133: ChildrenFiltered=2
|
||||||
|
bench_traversal_test.go:133: ChildrenFiltered=2
|
||||||
|
bench_traversal_test.go:133: ChildrenFiltered=2
|
||||||
|
bench_traversal_test.go:133: ChildrenFiltered=2
|
||||||
|
BenchmarkParent 50000 39067 ns/op
|
||||||
|
--- BENCH: BenchmarkParent
|
||||||
|
bench_traversal_test.go:149: Parent=55
|
||||||
|
bench_traversal_test.go:149: Parent=55
|
||||||
|
bench_traversal_test.go:149: Parent=55
|
||||||
|
bench_traversal_test.go:149: Parent=55
|
||||||
|
BenchmarkParentFiltered 50000 41450 ns/op
|
||||||
|
--- BENCH: BenchmarkParentFiltered
|
||||||
|
bench_traversal_test.go:165: ParentFiltered=4
|
||||||
|
bench_traversal_test.go:165: ParentFiltered=4
|
||||||
|
bench_traversal_test.go:165: ParentFiltered=4
|
||||||
|
bench_traversal_test.go:165: ParentFiltered=4
|
||||||
|
BenchmarkParents 20000 84864 ns/op
|
||||||
|
--- BENCH: BenchmarkParents
|
||||||
|
bench_traversal_test.go:181: Parents=73
|
||||||
|
bench_traversal_test.go:181: Parents=73
|
||||||
|
bench_traversal_test.go:181: Parents=73
|
||||||
|
bench_traversal_test.go:181: Parents=73
|
||||||
|
BenchmarkParentsFiltered 20000 87823 ns/op
|
||||||
|
--- BENCH: BenchmarkParentsFiltered
|
||||||
|
bench_traversal_test.go:197: ParentsFiltered=18
|
||||||
|
bench_traversal_test.go:197: ParentsFiltered=18
|
||||||
|
bench_traversal_test.go:197: ParentsFiltered=18
|
||||||
|
bench_traversal_test.go:197: ParentsFiltered=18
|
||||||
|
BenchmarkParentsUntil 50000 65986 ns/op
|
||||||
|
--- BENCH: BenchmarkParentsUntil
|
||||||
|
bench_traversal_test.go:213: ParentsUntil=52
|
||||||
|
bench_traversal_test.go:213: ParentsUntil=52
|
||||||
|
bench_traversal_test.go:213: ParentsUntil=52
|
||||||
|
bench_traversal_test.go:213: ParentsUntil=52
|
||||||
|
BenchmarkParentsUntilSelection 10000 149798 ns/op
|
||||||
|
--- BENCH: BenchmarkParentsUntilSelection
|
||||||
|
bench_traversal_test.go:230: ParentsUntilSelection=70
|
||||||
|
bench_traversal_test.go:230: ParentsUntilSelection=70
|
||||||
|
bench_traversal_test.go:230: ParentsUntilSelection=70
|
||||||
|
BenchmarkParentsUntilNodes 10000 148144 ns/op
|
||||||
|
--- BENCH: BenchmarkParentsUntilNodes
|
||||||
|
bench_traversal_test.go:248: ParentsUntilNodes=70
|
||||||
|
bench_traversal_test.go:248: ParentsUntilNodes=70
|
||||||
|
bench_traversal_test.go:248: ParentsUntilNodes=70
|
||||||
|
BenchmarkParentsFilteredUntil 100000 15579 ns/op
|
||||||
|
--- BENCH: BenchmarkParentsFilteredUntil
|
||||||
|
bench_traversal_test.go:264: ParentsFilteredUntil=2
|
||||||
|
bench_traversal_test.go:264: ParentsFilteredUntil=2
|
||||||
|
bench_traversal_test.go:264: ParentsFilteredUntil=2
|
||||||
|
bench_traversal_test.go:264: ParentsFilteredUntil=2
|
||||||
|
BenchmarkParentsFilteredUntilSelection 100000 19094 ns/op
|
||||||
|
--- BENCH: BenchmarkParentsFilteredUntilSelection
|
||||||
|
bench_traversal_test.go:281: ParentsFilteredUntilSelection=2
|
||||||
|
bench_traversal_test.go:281: ParentsFilteredUntilSelection=2
|
||||||
|
bench_traversal_test.go:281: ParentsFilteredUntilSelection=2
|
||||||
|
bench_traversal_test.go:281: ParentsFilteredUntilSelection=2
|
||||||
|
BenchmarkParentsFilteredUntilNodes 100000 19037 ns/op
|
||||||
|
--- BENCH: BenchmarkParentsFilteredUntilNodes
|
||||||
|
bench_traversal_test.go:299: ParentsFilteredUntilNodes=2
|
||||||
|
bench_traversal_test.go:299: ParentsFilteredUntilNodes=2
|
||||||
|
bench_traversal_test.go:299: ParentsFilteredUntilNodes=2
|
||||||
|
bench_traversal_test.go:299: ParentsFilteredUntilNodes=2
|
||||||
|
BenchmarkSiblings 50000 63891 ns/op
|
||||||
|
--- BENCH: BenchmarkSiblings
|
||||||
|
bench_traversal_test.go:315: Siblings=293
|
||||||
|
bench_traversal_test.go:315: Siblings=293
|
||||||
|
bench_traversal_test.go:315: Siblings=293
|
||||||
|
bench_traversal_test.go:315: Siblings=293
|
||||||
|
BenchmarkSiblingsFiltered 50000 70424 ns/op
|
||||||
|
--- BENCH: BenchmarkSiblingsFiltered
|
||||||
|
bench_traversal_test.go:331: SiblingsFiltered=46
|
||||||
|
bench_traversal_test.go:331: SiblingsFiltered=46
|
||||||
|
bench_traversal_test.go:331: SiblingsFiltered=46
|
||||||
|
bench_traversal_test.go:331: SiblingsFiltered=46
|
||||||
|
BenchmarkNext 200000 9350 ns/op
|
||||||
|
--- BENCH: BenchmarkNext
|
||||||
|
bench_traversal_test.go:347: Next=49
|
||||||
|
bench_traversal_test.go:347: Next=49
|
||||||
|
bench_traversal_test.go:347: Next=49
|
||||||
|
bench_traversal_test.go:347: Next=49
|
||||||
|
BenchmarkNextFiltered 200000 10929 ns/op
|
||||||
|
--- BENCH: BenchmarkNextFiltered
|
||||||
|
bench_traversal_test.go:363: NextFiltered=6
|
||||||
|
bench_traversal_test.go:363: NextFiltered=6
|
||||||
|
bench_traversal_test.go:363: NextFiltered=6
|
||||||
|
bench_traversal_test.go:363: NextFiltered=6
|
||||||
|
BenchmarkNextAll 50000 43398 ns/op
|
||||||
|
--- BENCH: BenchmarkNextAll
|
||||||
|
bench_traversal_test.go:379: NextAll=234
|
||||||
|
bench_traversal_test.go:379: NextAll=234
|
||||||
|
bench_traversal_test.go:379: NextAll=234
|
||||||
|
bench_traversal_test.go:379: NextAll=234
|
||||||
|
BenchmarkNextAllFiltered 50000 48519 ns/op
|
||||||
|
--- BENCH: BenchmarkNextAllFiltered
|
||||||
|
bench_traversal_test.go:395: NextAllFiltered=33
|
||||||
|
bench_traversal_test.go:395: NextAllFiltered=33
|
||||||
|
bench_traversal_test.go:395: NextAllFiltered=33
|
||||||
|
bench_traversal_test.go:395: NextAllFiltered=33
|
||||||
|
BenchmarkPrev 200000 9181 ns/op
|
||||||
|
--- BENCH: BenchmarkPrev
|
||||||
|
bench_traversal_test.go:411: Prev=49
|
||||||
|
bench_traversal_test.go:411: Prev=49
|
||||||
|
bench_traversal_test.go:411: Prev=49
|
||||||
|
bench_traversal_test.go:411: Prev=49
|
||||||
|
BenchmarkPrevFiltered 200000 10811 ns/op
|
||||||
|
--- BENCH: BenchmarkPrevFiltered
|
||||||
|
bench_traversal_test.go:429: PrevFiltered=7
|
||||||
|
bench_traversal_test.go:429: PrevFiltered=7
|
||||||
|
bench_traversal_test.go:429: PrevFiltered=7
|
||||||
|
bench_traversal_test.go:429: PrevFiltered=7
|
||||||
|
BenchmarkPrevAll 100000 15589 ns/op
|
||||||
|
--- BENCH: BenchmarkPrevAll
|
||||||
|
bench_traversal_test.go:445: PrevAll=78
|
||||||
|
bench_traversal_test.go:445: PrevAll=78
|
||||||
|
bench_traversal_test.go:445: PrevAll=78
|
||||||
|
bench_traversal_test.go:445: PrevAll=78
|
||||||
|
BenchmarkPrevAllFiltered 100000 17341 ns/op
|
||||||
|
--- BENCH: BenchmarkPrevAllFiltered
|
||||||
|
bench_traversal_test.go:461: PrevAllFiltered=6
|
||||||
|
bench_traversal_test.go:461: PrevAllFiltered=6
|
||||||
|
bench_traversal_test.go:461: PrevAllFiltered=6
|
||||||
|
bench_traversal_test.go:461: PrevAllFiltered=6
|
||||||
|
BenchmarkNextUntil 20000 80663 ns/op
|
||||||
|
--- BENCH: BenchmarkNextUntil
|
||||||
|
bench_traversal_test.go:477: NextUntil=84
|
||||||
|
bench_traversal_test.go:477: NextUntil=84
|
||||||
|
bench_traversal_test.go:477: NextUntil=84
|
||||||
|
bench_traversal_test.go:477: NextUntil=84
|
||||||
|
BenchmarkNextUntilSelection 50000 56496 ns/op
|
||||||
|
--- BENCH: BenchmarkNextUntilSelection
|
||||||
|
bench_traversal_test.go:494: NextUntilSelection=42
|
||||||
|
bench_traversal_test.go:494: NextUntilSelection=42
|
||||||
|
bench_traversal_test.go:494: NextUntilSelection=42
|
||||||
|
bench_traversal_test.go:494: NextUntilSelection=42
|
||||||
|
BenchmarkNextUntilNodes 100000 23729 ns/op
|
||||||
|
--- BENCH: BenchmarkNextUntilNodes
|
||||||
|
bench_traversal_test.go:512: NextUntilNodes=12
|
||||||
|
bench_traversal_test.go:512: NextUntilNodes=12
|
||||||
|
bench_traversal_test.go:512: NextUntilNodes=12
|
||||||
|
bench_traversal_test.go:512: NextUntilNodes=12
|
||||||
|
BenchmarkPrevUntil 10000 208267 ns/op
|
||||||
|
--- BENCH: BenchmarkPrevUntil
|
||||||
|
bench_traversal_test.go:528: PrevUntil=238
|
||||||
|
bench_traversal_test.go:528: PrevUntil=238
|
||||||
|
bench_traversal_test.go:528: PrevUntil=238
|
||||||
|
BenchmarkPrevUntilSelection 50000 72119 ns/op
|
||||||
|
--- BENCH: BenchmarkPrevUntilSelection
|
||||||
|
bench_traversal_test.go:545: PrevUntilSelection=49
|
||||||
|
bench_traversal_test.go:545: PrevUntilSelection=49
|
||||||
|
bench_traversal_test.go:545: PrevUntilSelection=49
|
||||||
|
bench_traversal_test.go:545: PrevUntilSelection=49
|
||||||
|
BenchmarkPrevUntilNodes 100000 18549 ns/op
|
||||||
|
--- BENCH: BenchmarkPrevUntilNodes
|
||||||
|
bench_traversal_test.go:563: PrevUntilNodes=11
|
||||||
|
bench_traversal_test.go:563: PrevUntilNodes=11
|
||||||
|
bench_traversal_test.go:563: PrevUntilNodes=11
|
||||||
|
bench_traversal_test.go:563: PrevUntilNodes=11
|
||||||
|
BenchmarkNextFilteredUntil 50000 42339 ns/op
|
||||||
|
--- BENCH: BenchmarkNextFilteredUntil
|
||||||
|
bench_traversal_test.go:579: NextFilteredUntil=22
|
||||||
|
bench_traversal_test.go:579: NextFilteredUntil=22
|
||||||
|
bench_traversal_test.go:579: NextFilteredUntil=22
|
||||||
|
bench_traversal_test.go:579: NextFilteredUntil=22
|
||||||
|
BenchmarkNextFilteredUntilSelection 50000 61916 ns/op
|
||||||
|
--- BENCH: BenchmarkNextFilteredUntilSelection
|
||||||
|
bench_traversal_test.go:596: NextFilteredUntilSelection=22
|
||||||
|
bench_traversal_test.go:596: NextFilteredUntilSelection=22
|
||||||
|
bench_traversal_test.go:596: NextFilteredUntilSelection=22
|
||||||
|
bench_traversal_test.go:596: NextFilteredUntilSelection=22
|
||||||
|
BenchmarkNextFilteredUntilNodes 50000 62139 ns/op
|
||||||
|
--- BENCH: BenchmarkNextFilteredUntilNodes
|
||||||
|
bench_traversal_test.go:614: NextFilteredUntilNodes=22
|
||||||
|
bench_traversal_test.go:614: NextFilteredUntilNodes=22
|
||||||
|
bench_traversal_test.go:614: NextFilteredUntilNodes=22
|
||||||
|
bench_traversal_test.go:614: NextFilteredUntilNodes=22
|
||||||
|
BenchmarkPrevFilteredUntil 50000 43409 ns/op
|
||||||
|
--- BENCH: BenchmarkPrevFilteredUntil
|
||||||
|
bench_traversal_test.go:630: PrevFilteredUntil=20
|
||||||
|
bench_traversal_test.go:630: PrevFilteredUntil=20
|
||||||
|
bench_traversal_test.go:630: PrevFilteredUntil=20
|
||||||
|
bench_traversal_test.go:630: PrevFilteredUntil=20
|
||||||
|
BenchmarkPrevFilteredUntilSelection 50000 63768 ns/op
|
||||||
|
--- BENCH: BenchmarkPrevFilteredUntilSelection
|
||||||
|
bench_traversal_test.go:647: PrevFilteredUntilSelection=20
|
||||||
|
bench_traversal_test.go:647: PrevFilteredUntilSelection=20
|
||||||
|
bench_traversal_test.go:647: PrevFilteredUntilSelection=20
|
||||||
|
bench_traversal_test.go:647: PrevFilteredUntilSelection=20
|
||||||
|
BenchmarkPrevFilteredUntilNodes 50000 63543 ns/op
|
||||||
|
--- BENCH: BenchmarkPrevFilteredUntilNodes
|
||||||
|
bench_traversal_test.go:665: PrevFilteredUntilNodes=20
|
||||||
|
bench_traversal_test.go:665: PrevFilteredUntilNodes=20
|
||||||
|
bench_traversal_test.go:665: PrevFilteredUntilNodes=20
|
||||||
|
bench_traversal_test.go:665: PrevFilteredUntilNodes=20
|
||||||
|
BenchmarkClosest 500000 5110 ns/op
|
||||||
|
--- BENCH: BenchmarkClosest
|
||||||
|
bench_traversal_test.go:681: Closest=2
|
||||||
|
bench_traversal_test.go:681: Closest=2
|
||||||
|
bench_traversal_test.go:681: Closest=2
|
||||||
|
bench_traversal_test.go:681: Closest=2
|
||||||
|
BenchmarkClosestSelection 5000000 629 ns/op
|
||||||
|
--- BENCH: BenchmarkClosestSelection
|
||||||
|
bench_traversal_test.go:698: ClosestSelection=2
|
||||||
|
bench_traversal_test.go:698: ClosestSelection=2
|
||||||
|
bench_traversal_test.go:698: ClosestSelection=2
|
||||||
|
bench_traversal_test.go:698: ClosestSelection=2
|
||||||
|
bench_traversal_test.go:698: ClosestSelection=2
|
||||||
|
BenchmarkClosestNodes 5000000 627 ns/op
|
||||||
|
--- BENCH: BenchmarkClosestNodes
|
||||||
|
bench_traversal_test.go:715: ClosestNodes=2
|
||||||
|
bench_traversal_test.go:715: ClosestNodes=2
|
||||||
|
bench_traversal_test.go:715: ClosestNodes=2
|
||||||
|
bench_traversal_test.go:715: ClosestNodes=2
|
||||||
|
bench_traversal_test.go:715: ClosestNodes=2
|
||||||
|
ok github.com/PuerkitoBio/goquery 215.785s
|
112
Godeps/_workspace/src/github.com/PuerkitoBio/goquery/bench_array_test.go
generated
vendored
Normal file
112
Godeps/_workspace/src/github.com/PuerkitoBio/goquery/bench_array_test.go
generated
vendored
Normal file
|
@ -0,0 +1,112 @@
|
||||||
|
package goquery
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func BenchmarkFirst(b *testing.B) {
|
||||||
|
b.StopTimer()
|
||||||
|
sel := DocB().Find("dd")
|
||||||
|
b.StartTimer()
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
sel.First()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkLast(b *testing.B) {
|
||||||
|
b.StopTimer()
|
||||||
|
sel := DocB().Find("dd")
|
||||||
|
b.StartTimer()
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
sel.Last()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkEq(b *testing.B) {
|
||||||
|
b.StopTimer()
|
||||||
|
sel := DocB().Find("dd")
|
||||||
|
j := 0
|
||||||
|
b.StartTimer()
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
sel.Eq(j)
|
||||||
|
if j++; j >= sel.Length() {
|
||||||
|
j = 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkSlice(b *testing.B) {
|
||||||
|
b.StopTimer()
|
||||||
|
sel := DocB().Find("dd")
|
||||||
|
j := 0
|
||||||
|
b.StartTimer()
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
sel.Slice(j, j+4)
|
||||||
|
if j++; j >= (sel.Length() - 4) {
|
||||||
|
j = 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkGet(b *testing.B) {
|
||||||
|
b.StopTimer()
|
||||||
|
sel := DocB().Find("dd")
|
||||||
|
j := 0
|
||||||
|
b.StartTimer()
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
sel.Get(j)
|
||||||
|
if j++; j >= sel.Length() {
|
||||||
|
j = 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkIndex(b *testing.B) {
|
||||||
|
var j int
|
||||||
|
|
||||||
|
b.StopTimer()
|
||||||
|
sel := DocB().Find("#Main")
|
||||||
|
b.StartTimer()
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
j = sel.Index()
|
||||||
|
}
|
||||||
|
b.Logf("Index=%d", j)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkIndexSelector(b *testing.B) {
|
||||||
|
var j int
|
||||||
|
|
||||||
|
b.StopTimer()
|
||||||
|
sel := DocB().Find("#manual-nav dl dd:nth-child(1)")
|
||||||
|
b.StartTimer()
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
j = sel.IndexSelector("dd")
|
||||||
|
}
|
||||||
|
b.Logf("IndexSelector=%d", j)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkIndexOfNode(b *testing.B) {
|
||||||
|
var j int
|
||||||
|
|
||||||
|
b.StopTimer()
|
||||||
|
sel := DocB().Find("span a")
|
||||||
|
sel2 := DocB().Find("span a:nth-child(3)")
|
||||||
|
n := sel2.Get(0)
|
||||||
|
b.StartTimer()
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
j = sel.IndexOfNode(n)
|
||||||
|
}
|
||||||
|
b.Logf("IndexOfNode=%d", j)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkIndexOfSelection(b *testing.B) {
|
||||||
|
var j int
|
||||||
|
b.StopTimer()
|
||||||
|
sel := DocB().Find("span a")
|
||||||
|
sel2 := DocB().Find("span a:nth-child(3)")
|
||||||
|
b.StartTimer()
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
j = sel.IndexOfSelection(sel2)
|
||||||
|
}
|
||||||
|
b.Logf("IndexOfSelection=%d", j)
|
||||||
|
}
|
42
Godeps/_workspace/src/github.com/PuerkitoBio/goquery/bench_example_test.go
generated
vendored
Normal file
42
Godeps/_workspace/src/github.com/PuerkitoBio/goquery/bench_example_test.go
generated
vendored
Normal file
|
@ -0,0 +1,42 @@
|
||||||
|
package goquery
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"fmt"
|
||||||
|
"strconv"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func BenchmarkMetalReviewExample(b *testing.B) {
|
||||||
|
var n int
|
||||||
|
var buf bytes.Buffer
|
||||||
|
|
||||||
|
b.StopTimer()
|
||||||
|
doc := loadDoc("metalreview.html")
|
||||||
|
b.StartTimer()
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
doc.Find(".slider-row:nth-child(1) .slider-item").Each(func(i int, s *Selection) {
|
||||||
|
var band, title string
|
||||||
|
var score float64
|
||||||
|
var e error
|
||||||
|
|
||||||
|
n++
|
||||||
|
// For each item found, get the band, title and score, and print it
|
||||||
|
band = s.Find("strong").Text()
|
||||||
|
title = s.Find("em").Text()
|
||||||
|
if score, e = strconv.ParseFloat(s.Find(".score").Text(), 64); e != nil {
|
||||||
|
// Not a valid float, ignore score
|
||||||
|
if n <= 4 {
|
||||||
|
buf.WriteString(fmt.Sprintf("Review %d: %s - %s.\n", i, band, title))
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Print all, including score
|
||||||
|
if n <= 4 {
|
||||||
|
buf.WriteString(fmt.Sprintf("Review %d: %s - %s (%2.1f).\n", i, band, title, score))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
b.Log(buf.String())
|
||||||
|
b.Logf("MetalReviewExample=%d", n)
|
||||||
|
}
|
72
Godeps/_workspace/src/github.com/PuerkitoBio/goquery/bench_expand_test.go
generated
vendored
Normal file
72
Godeps/_workspace/src/github.com/PuerkitoBio/goquery/bench_expand_test.go
generated
vendored
Normal file
|
@ -0,0 +1,72 @@
|
||||||
|
package goquery
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func BenchmarkAdd(b *testing.B) {
|
||||||
|
var n int
|
||||||
|
|
||||||
|
b.StopTimer()
|
||||||
|
sel := DocB().Find("dd")
|
||||||
|
b.StartTimer()
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
if n == 0 {
|
||||||
|
n = sel.Add("h2[title]").Length()
|
||||||
|
} else {
|
||||||
|
sel.Add("h2[title]")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
b.Logf("Add=%d", n)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkAddSelection(b *testing.B) {
|
||||||
|
var n int
|
||||||
|
|
||||||
|
b.StopTimer()
|
||||||
|
sel := DocB().Find("dd")
|
||||||
|
sel2 := DocB().Find("h2[title]")
|
||||||
|
b.StartTimer()
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
if n == 0 {
|
||||||
|
n = sel.AddSelection(sel2).Length()
|
||||||
|
} else {
|
||||||
|
sel.AddSelection(sel2)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
b.Logf("AddSelection=%d", n)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkAddNodes(b *testing.B) {
|
||||||
|
var n int
|
||||||
|
|
||||||
|
b.StopTimer()
|
||||||
|
sel := DocB().Find("dd")
|
||||||
|
sel2 := DocB().Find("h2[title]")
|
||||||
|
nodes := sel2.Nodes
|
||||||
|
b.StartTimer()
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
if n == 0 {
|
||||||
|
n = sel.AddNodes(nodes...).Length()
|
||||||
|
} else {
|
||||||
|
sel.AddNodes(nodes...)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
b.Logf("AddNodes=%d", n)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkAndSelf(b *testing.B) {
|
||||||
|
var n int
|
||||||
|
|
||||||
|
b.StopTimer()
|
||||||
|
sel := DocB().Find("dd").Parent()
|
||||||
|
b.StartTimer()
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
if n == 0 {
|
||||||
|
n = sel.AndSelf().Length()
|
||||||
|
} else {
|
||||||
|
sel.AndSelf()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
b.Logf("AndSelf=%d", n)
|
||||||
|
}
|
212
Godeps/_workspace/src/github.com/PuerkitoBio/goquery/bench_filter_test.go
generated
vendored
Normal file
212
Godeps/_workspace/src/github.com/PuerkitoBio/goquery/bench_filter_test.go
generated
vendored
Normal file
|
@ -0,0 +1,212 @@
|
||||||
|
package goquery
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func BenchmarkFilter(b *testing.B) {
|
||||||
|
var n int
|
||||||
|
|
||||||
|
b.StopTimer()
|
||||||
|
sel := DocW().Find("li")
|
||||||
|
b.StartTimer()
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
if n == 0 {
|
||||||
|
n = sel.Filter(".toclevel-1").Length()
|
||||||
|
} else {
|
||||||
|
sel.Filter(".toclevel-1")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
b.Logf("Filter=%d", n)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkNot(b *testing.B) {
|
||||||
|
var n int
|
||||||
|
|
||||||
|
b.StopTimer()
|
||||||
|
sel := DocW().Find("li")
|
||||||
|
b.StartTimer()
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
if n == 0 {
|
||||||
|
n = sel.Not(".toclevel-2").Length()
|
||||||
|
} else {
|
||||||
|
sel.Filter(".toclevel-2")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
b.Logf("Not=%d", n)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkFilterFunction(b *testing.B) {
|
||||||
|
var n int
|
||||||
|
|
||||||
|
b.StopTimer()
|
||||||
|
sel := DocW().Find("li")
|
||||||
|
f := func(i int, s *Selection) bool {
|
||||||
|
return len(s.Get(0).Attr) > 0
|
||||||
|
}
|
||||||
|
b.StartTimer()
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
if n == 0 {
|
||||||
|
n = sel.FilterFunction(f).Length()
|
||||||
|
} else {
|
||||||
|
sel.FilterFunction(f)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
b.Logf("FilterFunction=%d", n)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkNotFunction(b *testing.B) {
|
||||||
|
var n int
|
||||||
|
|
||||||
|
b.StopTimer()
|
||||||
|
sel := DocW().Find("li")
|
||||||
|
f := func(i int, s *Selection) bool {
|
||||||
|
return len(s.Get(0).Attr) > 0
|
||||||
|
}
|
||||||
|
b.StartTimer()
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
if n == 0 {
|
||||||
|
n = sel.NotFunction(f).Length()
|
||||||
|
} else {
|
||||||
|
sel.NotFunction(f)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
b.Logf("NotFunction=%d", n)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkFilterNodes(b *testing.B) {
|
||||||
|
var n int
|
||||||
|
|
||||||
|
b.StopTimer()
|
||||||
|
sel := DocW().Find("li")
|
||||||
|
sel2 := DocW().Find(".toclevel-2")
|
||||||
|
nodes := sel2.Nodes
|
||||||
|
b.StartTimer()
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
if n == 0 {
|
||||||
|
n = sel.FilterNodes(nodes...).Length()
|
||||||
|
} else {
|
||||||
|
sel.FilterNodes(nodes...)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
b.Logf("FilterNodes=%d", n)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkNotNodes(b *testing.B) {
|
||||||
|
var n int
|
||||||
|
|
||||||
|
b.StopTimer()
|
||||||
|
sel := DocW().Find("li")
|
||||||
|
sel2 := DocW().Find(".toclevel-1")
|
||||||
|
nodes := sel2.Nodes
|
||||||
|
b.StartTimer()
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
if n == 0 {
|
||||||
|
n = sel.NotNodes(nodes...).Length()
|
||||||
|
} else {
|
||||||
|
sel.NotNodes(nodes...)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
b.Logf("NotNodes=%d", n)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkFilterSelection(b *testing.B) {
|
||||||
|
var n int
|
||||||
|
|
||||||
|
b.StopTimer()
|
||||||
|
sel := DocW().Find("li")
|
||||||
|
sel2 := DocW().Find(".toclevel-2")
|
||||||
|
b.StartTimer()
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
if n == 0 {
|
||||||
|
n = sel.FilterSelection(sel2).Length()
|
||||||
|
} else {
|
||||||
|
sel.FilterSelection(sel2)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
b.Logf("FilterSelection=%d", n)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkNotSelection(b *testing.B) {
|
||||||
|
var n int
|
||||||
|
|
||||||
|
b.StopTimer()
|
||||||
|
sel := DocW().Find("li")
|
||||||
|
sel2 := DocW().Find(".toclevel-1")
|
||||||
|
b.StartTimer()
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
if n == 0 {
|
||||||
|
n = sel.NotSelection(sel2).Length()
|
||||||
|
} else {
|
||||||
|
sel.NotSelection(sel2)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
b.Logf("NotSelection=%d", n)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkHas(b *testing.B) {
|
||||||
|
var n int
|
||||||
|
|
||||||
|
b.StopTimer()
|
||||||
|
sel := DocW().Find("h2")
|
||||||
|
b.StartTimer()
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
if n == 0 {
|
||||||
|
n = sel.Has(".editsection").Length()
|
||||||
|
} else {
|
||||||
|
sel.Has(".editsection")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
b.Logf("Has=%d", n)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkHasNodes(b *testing.B) {
|
||||||
|
var n int
|
||||||
|
|
||||||
|
b.StopTimer()
|
||||||
|
sel := DocW().Find("li")
|
||||||
|
sel2 := DocW().Find(".tocnumber")
|
||||||
|
nodes := sel2.Nodes
|
||||||
|
b.StartTimer()
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
if n == 0 {
|
||||||
|
n = sel.HasNodes(nodes...).Length()
|
||||||
|
} else {
|
||||||
|
sel.HasNodes(nodes...)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
b.Logf("HasNodes=%d", n)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkHasSelection(b *testing.B) {
|
||||||
|
var n int
|
||||||
|
|
||||||
|
b.StopTimer()
|
||||||
|
sel := DocW().Find("li")
|
||||||
|
sel2 := DocW().Find(".tocnumber")
|
||||||
|
b.StartTimer()
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
if n == 0 {
|
||||||
|
n = sel.HasSelection(sel2).Length()
|
||||||
|
} else {
|
||||||
|
sel.HasSelection(sel2)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
b.Logf("HasSelection=%d", n)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkEnd(b *testing.B) {
|
||||||
|
var n int
|
||||||
|
|
||||||
|
b.StopTimer()
|
||||||
|
sel := DocW().Find("li").Has(".tocnumber")
|
||||||
|
b.StartTimer()
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
if n == 0 {
|
||||||
|
n = sel.End().Length()
|
||||||
|
} else {
|
||||||
|
sel.End()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
b.Logf("End=%d", n)
|
||||||
|
}
|
62
Godeps/_workspace/src/github.com/PuerkitoBio/goquery/bench_iteration_test.go
generated
vendored
Normal file
62
Godeps/_workspace/src/github.com/PuerkitoBio/goquery/bench_iteration_test.go
generated
vendored
Normal file
|
@ -0,0 +1,62 @@
|
||||||
|
package goquery
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func BenchmarkEach(b *testing.B) {
|
||||||
|
var tmp, n int
|
||||||
|
|
||||||
|
b.StopTimer()
|
||||||
|
sel := DocW().Find("td")
|
||||||
|
f := func(i int, s *Selection) {
|
||||||
|
tmp++
|
||||||
|
}
|
||||||
|
b.StartTimer()
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
sel.Each(f)
|
||||||
|
if n == 0 {
|
||||||
|
n = tmp
|
||||||
|
}
|
||||||
|
}
|
||||||
|
b.Logf("Each=%d", n)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkMap(b *testing.B) {
|
||||||
|
var tmp, n int
|
||||||
|
|
||||||
|
b.StopTimer()
|
||||||
|
sel := DocW().Find("td")
|
||||||
|
f := func(i int, s *Selection) string {
|
||||||
|
tmp++
|
||||||
|
return string(tmp)
|
||||||
|
}
|
||||||
|
b.StartTimer()
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
sel.Map(f)
|
||||||
|
if n == 0 {
|
||||||
|
n = tmp
|
||||||
|
}
|
||||||
|
}
|
||||||
|
b.Logf("Map=%d", n)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkEachWithBreak(b *testing.B) {
|
||||||
|
var tmp, n int
|
||||||
|
|
||||||
|
b.StopTimer()
|
||||||
|
sel := DocW().Find("td")
|
||||||
|
f := func(i int, s *Selection) bool {
|
||||||
|
tmp++
|
||||||
|
return tmp < 10
|
||||||
|
}
|
||||||
|
b.StartTimer()
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
tmp = 0
|
||||||
|
sel.EachWithBreak(f)
|
||||||
|
if n == 0 {
|
||||||
|
n = tmp
|
||||||
|
}
|
||||||
|
}
|
||||||
|
b.Logf("Each=%d", n)
|
||||||
|
}
|
47
Godeps/_workspace/src/github.com/PuerkitoBio/goquery/bench_property_test.go
generated
vendored
Normal file
47
Godeps/_workspace/src/github.com/PuerkitoBio/goquery/bench_property_test.go
generated
vendored
Normal file
|
@ -0,0 +1,47 @@
|
||||||
|
package goquery
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func BenchmarkAttr(b *testing.B) {
|
||||||
|
var s string
|
||||||
|
|
||||||
|
b.StopTimer()
|
||||||
|
sel := DocW().Find("h1")
|
||||||
|
b.StartTimer()
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
s, _ = sel.Attr("id")
|
||||||
|
}
|
||||||
|
b.Logf("Attr=%s", s)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkText(b *testing.B) {
|
||||||
|
b.StopTimer()
|
||||||
|
sel := DocW().Find("h2")
|
||||||
|
b.StartTimer()
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
sel.Text()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkLength(b *testing.B) {
|
||||||
|
var n int
|
||||||
|
|
||||||
|
b.StopTimer()
|
||||||
|
sel := DocW().Find("h2")
|
||||||
|
b.StartTimer()
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
n = sel.Length()
|
||||||
|
}
|
||||||
|
b.Logf("Length=%d", n)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkHtml(b *testing.B) {
|
||||||
|
b.StopTimer()
|
||||||
|
sel := DocW().Find("h2")
|
||||||
|
b.StartTimer()
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
sel.Html()
|
||||||
|
}
|
||||||
|
}
|
97
Godeps/_workspace/src/github.com/PuerkitoBio/goquery/bench_query_test.go
generated
vendored
Normal file
97
Godeps/_workspace/src/github.com/PuerkitoBio/goquery/bench_query_test.go
generated
vendored
Normal file
|
@ -0,0 +1,97 @@
|
||||||
|
package goquery
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func BenchmarkIs(b *testing.B) {
|
||||||
|
var y bool
|
||||||
|
|
||||||
|
b.StopTimer()
|
||||||
|
sel := DocW().Find("li")
|
||||||
|
b.StartTimer()
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
y = sel.Is(".toclevel-2")
|
||||||
|
}
|
||||||
|
b.Logf("Is=%v", y)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkIsPositional(b *testing.B) {
|
||||||
|
var y bool
|
||||||
|
|
||||||
|
b.StopTimer()
|
||||||
|
sel := DocW().Find("li")
|
||||||
|
b.StartTimer()
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
y = sel.Is("li:nth-child(2)")
|
||||||
|
}
|
||||||
|
b.Logf("IsPositional=%v", y)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkIsFunction(b *testing.B) {
|
||||||
|
var y bool
|
||||||
|
|
||||||
|
b.StopTimer()
|
||||||
|
sel := DocW().Find(".toclevel-1")
|
||||||
|
f := func(i int, s *Selection) bool {
|
||||||
|
return i == 8
|
||||||
|
}
|
||||||
|
b.StartTimer()
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
y = sel.IsFunction(f)
|
||||||
|
}
|
||||||
|
b.Logf("IsFunction=%v", y)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkIsSelection(b *testing.B) {
|
||||||
|
var y bool
|
||||||
|
|
||||||
|
b.StopTimer()
|
||||||
|
sel := DocW().Find("li")
|
||||||
|
sel2 := DocW().Find(".toclevel-2")
|
||||||
|
b.StartTimer()
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
y = sel.IsSelection(sel2)
|
||||||
|
}
|
||||||
|
b.Logf("IsSelection=%v", y)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkIsNodes(b *testing.B) {
|
||||||
|
var y bool
|
||||||
|
|
||||||
|
b.StopTimer()
|
||||||
|
sel := DocW().Find("li")
|
||||||
|
sel2 := DocW().Find(".toclevel-2")
|
||||||
|
nodes := sel2.Nodes
|
||||||
|
b.StartTimer()
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
y = sel.IsNodes(nodes...)
|
||||||
|
}
|
||||||
|
b.Logf("IsNodes=%v", y)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkHasClass(b *testing.B) {
|
||||||
|
var y bool
|
||||||
|
|
||||||
|
b.StopTimer()
|
||||||
|
sel := DocW().Find("span")
|
||||||
|
b.StartTimer()
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
y = sel.HasClass("official")
|
||||||
|
}
|
||||||
|
b.Logf("HasClass=%v", y)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkContains(b *testing.B) {
|
||||||
|
var y bool
|
||||||
|
|
||||||
|
b.StopTimer()
|
||||||
|
sel := DocW().Find("span.url")
|
||||||
|
sel2 := DocW().Find("a[rel=\"nofollow\"]")
|
||||||
|
node := sel2.Nodes[0]
|
||||||
|
b.StartTimer()
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
y = sel.Contains(node)
|
||||||
|
}
|
||||||
|
b.Logf("Contains=%v", y)
|
||||||
|
}
|
716
Godeps/_workspace/src/github.com/PuerkitoBio/goquery/bench_traversal_test.go
generated
vendored
Normal file
716
Godeps/_workspace/src/github.com/PuerkitoBio/goquery/bench_traversal_test.go
generated
vendored
Normal file
|
@ -0,0 +1,716 @@
|
||||||
|
package goquery
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func BenchmarkFind(b *testing.B) {
|
||||||
|
var n int
|
||||||
|
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
if n == 0 {
|
||||||
|
n = DocB().Find("dd").Length()
|
||||||
|
|
||||||
|
} else {
|
||||||
|
DocB().Find("dd")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
b.Logf("Find=%d", n)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkFindWithinSelection(b *testing.B) {
|
||||||
|
var n int
|
||||||
|
|
||||||
|
b.StopTimer()
|
||||||
|
sel := DocW().Find("ul")
|
||||||
|
b.StartTimer()
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
if n == 0 {
|
||||||
|
n = sel.Find("a[class]").Length()
|
||||||
|
} else {
|
||||||
|
sel.Find("a[class]")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
b.Logf("FindWithinSelection=%d", n)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkFindSelection(b *testing.B) {
|
||||||
|
var n int
|
||||||
|
|
||||||
|
b.StopTimer()
|
||||||
|
sel := DocW().Find("ul")
|
||||||
|
sel2 := DocW().Find("span")
|
||||||
|
b.StartTimer()
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
if n == 0 {
|
||||||
|
n = sel.FindSelection(sel2).Length()
|
||||||
|
} else {
|
||||||
|
sel.FindSelection(sel2)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
b.Logf("FindSelection=%d", n)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkFindNodes(b *testing.B) {
|
||||||
|
var n int
|
||||||
|
|
||||||
|
b.StopTimer()
|
||||||
|
sel := DocW().Find("ul")
|
||||||
|
sel2 := DocW().Find("span")
|
||||||
|
nodes := sel2.Nodes
|
||||||
|
b.StartTimer()
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
if n == 0 {
|
||||||
|
n = sel.FindNodes(nodes...).Length()
|
||||||
|
} else {
|
||||||
|
sel.FindNodes(nodes...)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
b.Logf("FindNodes=%d", n)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkContents(b *testing.B) {
|
||||||
|
var n int
|
||||||
|
|
||||||
|
b.StopTimer()
|
||||||
|
sel := DocW().Find(".toclevel-1")
|
||||||
|
b.StartTimer()
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
if n == 0 {
|
||||||
|
n = sel.Contents().Length()
|
||||||
|
} else {
|
||||||
|
sel.Contents()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
b.Logf("Contents=%d", n)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkContentsFiltered(b *testing.B) {
|
||||||
|
var n int
|
||||||
|
|
||||||
|
b.StopTimer()
|
||||||
|
sel := DocW().Find(".toclevel-1")
|
||||||
|
b.StartTimer()
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
if n == 0 {
|
||||||
|
n = sel.ContentsFiltered("a[href=\"#Examples\"]").Length()
|
||||||
|
} else {
|
||||||
|
sel.ContentsFiltered("a[href=\"#Examples\"]")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
b.Logf("ContentsFiltered=%d", n)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkChildren(b *testing.B) {
|
||||||
|
var n int
|
||||||
|
|
||||||
|
b.StopTimer()
|
||||||
|
sel := DocW().Find(".toclevel-2")
|
||||||
|
b.StartTimer()
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
if n == 0 {
|
||||||
|
n = sel.Children().Length()
|
||||||
|
} else {
|
||||||
|
sel.Children()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
b.Logf("Children=%d", n)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkChildrenFiltered(b *testing.B) {
|
||||||
|
var n int
|
||||||
|
|
||||||
|
b.StopTimer()
|
||||||
|
sel := DocW().Find("h3")
|
||||||
|
b.StartTimer()
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
if n == 0 {
|
||||||
|
n = sel.ChildrenFiltered(".editsection").Length()
|
||||||
|
} else {
|
||||||
|
sel.ChildrenFiltered(".editsection")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
b.Logf("ChildrenFiltered=%d", n)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkParent(b *testing.B) {
|
||||||
|
var n int
|
||||||
|
|
||||||
|
b.StopTimer()
|
||||||
|
sel := DocW().Find("li")
|
||||||
|
b.StartTimer()
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
if n == 0 {
|
||||||
|
n = sel.Parent().Length()
|
||||||
|
} else {
|
||||||
|
sel.Parent()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
b.Logf("Parent=%d", n)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkParentFiltered(b *testing.B) {
|
||||||
|
var n int
|
||||||
|
|
||||||
|
b.StopTimer()
|
||||||
|
sel := DocW().Find("li")
|
||||||
|
b.StartTimer()
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
if n == 0 {
|
||||||
|
n = sel.ParentFiltered("ul[id]").Length()
|
||||||
|
} else {
|
||||||
|
sel.ParentFiltered("ul[id]")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
b.Logf("ParentFiltered=%d", n)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkParents(b *testing.B) {
|
||||||
|
var n int
|
||||||
|
|
||||||
|
b.StopTimer()
|
||||||
|
sel := DocW().Find("th a")
|
||||||
|
b.StartTimer()
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
if n == 0 {
|
||||||
|
n = sel.Parents().Length()
|
||||||
|
} else {
|
||||||
|
sel.Parents()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
b.Logf("Parents=%d", n)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkParentsFiltered(b *testing.B) {
|
||||||
|
var n int
|
||||||
|
|
||||||
|
b.StopTimer()
|
||||||
|
sel := DocW().Find("th a")
|
||||||
|
b.StartTimer()
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
if n == 0 {
|
||||||
|
n = sel.ParentsFiltered("tr").Length()
|
||||||
|
} else {
|
||||||
|
sel.ParentsFiltered("tr")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
b.Logf("ParentsFiltered=%d", n)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkParentsUntil(b *testing.B) {
|
||||||
|
var n int
|
||||||
|
|
||||||
|
b.StopTimer()
|
||||||
|
sel := DocW().Find("th a")
|
||||||
|
b.StartTimer()
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
if n == 0 {
|
||||||
|
n = sel.ParentsUntil("table").Length()
|
||||||
|
} else {
|
||||||
|
sel.ParentsUntil("table")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
b.Logf("ParentsUntil=%d", n)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkParentsUntilSelection(b *testing.B) {
|
||||||
|
var n int
|
||||||
|
|
||||||
|
b.StopTimer()
|
||||||
|
sel := DocW().Find("th a")
|
||||||
|
sel2 := DocW().Find("#content")
|
||||||
|
b.StartTimer()
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
if n == 0 {
|
||||||
|
n = sel.ParentsUntilSelection(sel2).Length()
|
||||||
|
} else {
|
||||||
|
sel.ParentsUntilSelection(sel2)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
b.Logf("ParentsUntilSelection=%d", n)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkParentsUntilNodes(b *testing.B) {
|
||||||
|
var n int
|
||||||
|
|
||||||
|
b.StopTimer()
|
||||||
|
sel := DocW().Find("th a")
|
||||||
|
sel2 := DocW().Find("#content")
|
||||||
|
nodes := sel2.Nodes
|
||||||
|
b.StartTimer()
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
if n == 0 {
|
||||||
|
n = sel.ParentsUntilNodes(nodes...).Length()
|
||||||
|
} else {
|
||||||
|
sel.ParentsUntilNodes(nodes...)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
b.Logf("ParentsUntilNodes=%d", n)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkParentsFilteredUntil(b *testing.B) {
|
||||||
|
var n int
|
||||||
|
|
||||||
|
b.StopTimer()
|
||||||
|
sel := DocW().Find(".toclevel-1 a")
|
||||||
|
b.StartTimer()
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
if n == 0 {
|
||||||
|
n = sel.ParentsFilteredUntil(":nth-child(1)", "ul").Length()
|
||||||
|
} else {
|
||||||
|
sel.ParentsFilteredUntil(":nth-child(1)", "ul")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
b.Logf("ParentsFilteredUntil=%d", n)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkParentsFilteredUntilSelection(b *testing.B) {
|
||||||
|
var n int
|
||||||
|
|
||||||
|
b.StopTimer()
|
||||||
|
sel := DocW().Find(".toclevel-1 a")
|
||||||
|
sel2 := DocW().Find("ul")
|
||||||
|
b.StartTimer()
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
if n == 0 {
|
||||||
|
n = sel.ParentsFilteredUntilSelection(":nth-child(1)", sel2).Length()
|
||||||
|
} else {
|
||||||
|
sel.ParentsFilteredUntilSelection(":nth-child(1)", sel2)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
b.Logf("ParentsFilteredUntilSelection=%d", n)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkParentsFilteredUntilNodes(b *testing.B) {
|
||||||
|
var n int
|
||||||
|
|
||||||
|
b.StopTimer()
|
||||||
|
sel := DocW().Find(".toclevel-1 a")
|
||||||
|
sel2 := DocW().Find("ul")
|
||||||
|
nodes := sel2.Nodes
|
||||||
|
b.StartTimer()
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
if n == 0 {
|
||||||
|
n = sel.ParentsFilteredUntilNodes(":nth-child(1)", nodes...).Length()
|
||||||
|
} else {
|
||||||
|
sel.ParentsFilteredUntilNodes(":nth-child(1)", nodes...)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
b.Logf("ParentsFilteredUntilNodes=%d", n)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkSiblings(b *testing.B) {
|
||||||
|
var n int
|
||||||
|
|
||||||
|
b.StopTimer()
|
||||||
|
sel := DocW().Find("ul li:nth-child(1)")
|
||||||
|
b.StartTimer()
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
if n == 0 {
|
||||||
|
n = sel.Siblings().Length()
|
||||||
|
} else {
|
||||||
|
sel.Siblings()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
b.Logf("Siblings=%d", n)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkSiblingsFiltered(b *testing.B) {
|
||||||
|
var n int
|
||||||
|
|
||||||
|
b.StopTimer()
|
||||||
|
sel := DocW().Find("ul li:nth-child(1)")
|
||||||
|
b.StartTimer()
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
if n == 0 {
|
||||||
|
n = sel.SiblingsFiltered("[class]").Length()
|
||||||
|
} else {
|
||||||
|
sel.SiblingsFiltered("[class]")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
b.Logf("SiblingsFiltered=%d", n)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkNext(b *testing.B) {
|
||||||
|
var n int
|
||||||
|
|
||||||
|
b.StopTimer()
|
||||||
|
sel := DocW().Find("li:nth-child(1)")
|
||||||
|
b.StartTimer()
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
if n == 0 {
|
||||||
|
n = sel.Next().Length()
|
||||||
|
} else {
|
||||||
|
sel.Next()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
b.Logf("Next=%d", n)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkNextFiltered(b *testing.B) {
|
||||||
|
var n int
|
||||||
|
|
||||||
|
b.StopTimer()
|
||||||
|
sel := DocW().Find("li:nth-child(1)")
|
||||||
|
b.StartTimer()
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
if n == 0 {
|
||||||
|
n = sel.NextFiltered("[class]").Length()
|
||||||
|
} else {
|
||||||
|
sel.NextFiltered("[class]")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
b.Logf("NextFiltered=%d", n)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkNextAll(b *testing.B) {
|
||||||
|
var n int
|
||||||
|
|
||||||
|
b.StopTimer()
|
||||||
|
sel := DocW().Find("li:nth-child(3)")
|
||||||
|
b.StartTimer()
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
if n == 0 {
|
||||||
|
n = sel.NextAll().Length()
|
||||||
|
} else {
|
||||||
|
sel.NextAll()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
b.Logf("NextAll=%d", n)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkNextAllFiltered(b *testing.B) {
|
||||||
|
var n int
|
||||||
|
|
||||||
|
b.StopTimer()
|
||||||
|
sel := DocW().Find("li:nth-child(3)")
|
||||||
|
b.StartTimer()
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
if n == 0 {
|
||||||
|
n = sel.NextAllFiltered("[class]").Length()
|
||||||
|
} else {
|
||||||
|
sel.NextAllFiltered("[class]")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
b.Logf("NextAllFiltered=%d", n)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkPrev(b *testing.B) {
|
||||||
|
var n int
|
||||||
|
|
||||||
|
b.StopTimer()
|
||||||
|
sel := DocW().Find("li:last-child")
|
||||||
|
b.StartTimer()
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
if n == 0 {
|
||||||
|
n = sel.Prev().Length()
|
||||||
|
} else {
|
||||||
|
sel.Prev()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
b.Logf("Prev=%d", n)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkPrevFiltered(b *testing.B) {
|
||||||
|
var n int
|
||||||
|
|
||||||
|
b.StopTimer()
|
||||||
|
sel := DocW().Find("li:last-child")
|
||||||
|
b.StartTimer()
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
if n == 0 {
|
||||||
|
n = sel.PrevFiltered("[class]").Length()
|
||||||
|
} else {
|
||||||
|
sel.PrevFiltered("[class]")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// There is one more Prev li with a class, compared to Next li with a class
|
||||||
|
// (confirmed by looking at the HTML, this is ok)
|
||||||
|
b.Logf("PrevFiltered=%d", n)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkPrevAll(b *testing.B) {
|
||||||
|
var n int
|
||||||
|
|
||||||
|
b.StopTimer()
|
||||||
|
sel := DocW().Find("li:nth-child(4)")
|
||||||
|
b.StartTimer()
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
if n == 0 {
|
||||||
|
n = sel.PrevAll().Length()
|
||||||
|
} else {
|
||||||
|
sel.PrevAll()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
b.Logf("PrevAll=%d", n)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkPrevAllFiltered(b *testing.B) {
|
||||||
|
var n int
|
||||||
|
|
||||||
|
b.StopTimer()
|
||||||
|
sel := DocW().Find("li:nth-child(4)")
|
||||||
|
b.StartTimer()
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
if n == 0 {
|
||||||
|
n = sel.PrevAllFiltered("[class]").Length()
|
||||||
|
} else {
|
||||||
|
sel.PrevAllFiltered("[class]")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
b.Logf("PrevAllFiltered=%d", n)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkNextUntil(b *testing.B) {
|
||||||
|
var n int
|
||||||
|
|
||||||
|
b.StopTimer()
|
||||||
|
sel := DocW().Find("li:first-child")
|
||||||
|
b.StartTimer()
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
if n == 0 {
|
||||||
|
n = sel.NextUntil(":nth-child(4)").Length()
|
||||||
|
} else {
|
||||||
|
sel.NextUntil(":nth-child(4)")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
b.Logf("NextUntil=%d", n)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkNextUntilSelection(b *testing.B) {
|
||||||
|
var n int
|
||||||
|
|
||||||
|
b.StopTimer()
|
||||||
|
sel := DocW().Find("h2")
|
||||||
|
sel2 := DocW().Find("ul")
|
||||||
|
b.StartTimer()
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
if n == 0 {
|
||||||
|
n = sel.NextUntilSelection(sel2).Length()
|
||||||
|
} else {
|
||||||
|
sel.NextUntilSelection(sel2)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
b.Logf("NextUntilSelection=%d", n)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkNextUntilNodes(b *testing.B) {
|
||||||
|
var n int
|
||||||
|
|
||||||
|
b.StopTimer()
|
||||||
|
sel := DocW().Find("h2")
|
||||||
|
sel2 := DocW().Find("p")
|
||||||
|
nodes := sel2.Nodes
|
||||||
|
b.StartTimer()
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
if n == 0 {
|
||||||
|
n = sel.NextUntilNodes(nodes...).Length()
|
||||||
|
} else {
|
||||||
|
sel.NextUntilNodes(nodes...)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
b.Logf("NextUntilNodes=%d", n)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkPrevUntil(b *testing.B) {
|
||||||
|
var n int
|
||||||
|
|
||||||
|
b.StopTimer()
|
||||||
|
sel := DocW().Find("li:last-child")
|
||||||
|
b.StartTimer()
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
if n == 0 {
|
||||||
|
n = sel.PrevUntil(":nth-child(4)").Length()
|
||||||
|
} else {
|
||||||
|
sel.PrevUntil(":nth-child(4)")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
b.Logf("PrevUntil=%d", n)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkPrevUntilSelection(b *testing.B) {
|
||||||
|
var n int
|
||||||
|
|
||||||
|
b.StopTimer()
|
||||||
|
sel := DocW().Find("h2")
|
||||||
|
sel2 := DocW().Find("ul")
|
||||||
|
b.StartTimer()
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
if n == 0 {
|
||||||
|
n = sel.PrevUntilSelection(sel2).Length()
|
||||||
|
} else {
|
||||||
|
sel.PrevUntilSelection(sel2)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
b.Logf("PrevUntilSelection=%d", n)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkPrevUntilNodes(b *testing.B) {
|
||||||
|
var n int
|
||||||
|
|
||||||
|
b.StopTimer()
|
||||||
|
sel := DocW().Find("h2")
|
||||||
|
sel2 := DocW().Find("p")
|
||||||
|
nodes := sel2.Nodes
|
||||||
|
b.StartTimer()
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
if n == 0 {
|
||||||
|
n = sel.PrevUntilNodes(nodes...).Length()
|
||||||
|
} else {
|
||||||
|
sel.PrevUntilNodes(nodes...)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
b.Logf("PrevUntilNodes=%d", n)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkNextFilteredUntil(b *testing.B) {
|
||||||
|
var n int
|
||||||
|
|
||||||
|
b.StopTimer()
|
||||||
|
sel := DocW().Find("h2")
|
||||||
|
b.StartTimer()
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
if n == 0 {
|
||||||
|
n = sel.NextFilteredUntil("p", "div").Length()
|
||||||
|
} else {
|
||||||
|
sel.NextFilteredUntil("p", "div")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
b.Logf("NextFilteredUntil=%d", n)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkNextFilteredUntilSelection(b *testing.B) {
|
||||||
|
var n int
|
||||||
|
|
||||||
|
b.StopTimer()
|
||||||
|
sel := DocW().Find("h2")
|
||||||
|
sel2 := DocW().Find("div")
|
||||||
|
b.StartTimer()
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
if n == 0 {
|
||||||
|
n = sel.NextFilteredUntilSelection("p", sel2).Length()
|
||||||
|
} else {
|
||||||
|
sel.NextFilteredUntilSelection("p", sel2)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
b.Logf("NextFilteredUntilSelection=%d", n)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkNextFilteredUntilNodes(b *testing.B) {
|
||||||
|
var n int
|
||||||
|
|
||||||
|
b.StopTimer()
|
||||||
|
sel := DocW().Find("h2")
|
||||||
|
sel2 := DocW().Find("div")
|
||||||
|
nodes := sel2.Nodes
|
||||||
|
b.StartTimer()
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
if n == 0 {
|
||||||
|
n = sel.NextFilteredUntilNodes("p", nodes...).Length()
|
||||||
|
} else {
|
||||||
|
sel.NextFilteredUntilNodes("p", nodes...)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
b.Logf("NextFilteredUntilNodes=%d", n)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkPrevFilteredUntil(b *testing.B) {
|
||||||
|
var n int
|
||||||
|
|
||||||
|
b.StopTimer()
|
||||||
|
sel := DocW().Find("h2")
|
||||||
|
b.StartTimer()
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
if n == 0 {
|
||||||
|
n = sel.PrevFilteredUntil("p", "div").Length()
|
||||||
|
} else {
|
||||||
|
sel.PrevFilteredUntil("p", "div")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
b.Logf("PrevFilteredUntil=%d", n)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkPrevFilteredUntilSelection(b *testing.B) {
|
||||||
|
var n int
|
||||||
|
|
||||||
|
b.StopTimer()
|
||||||
|
sel := DocW().Find("h2")
|
||||||
|
sel2 := DocW().Find("div")
|
||||||
|
b.StartTimer()
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
if n == 0 {
|
||||||
|
n = sel.PrevFilteredUntilSelection("p", sel2).Length()
|
||||||
|
} else {
|
||||||
|
sel.PrevFilteredUntilSelection("p", sel2)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
b.Logf("PrevFilteredUntilSelection=%d", n)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkPrevFilteredUntilNodes(b *testing.B) {
|
||||||
|
var n int
|
||||||
|
|
||||||
|
b.StopTimer()
|
||||||
|
sel := DocW().Find("h2")
|
||||||
|
sel2 := DocW().Find("div")
|
||||||
|
nodes := sel2.Nodes
|
||||||
|
b.StartTimer()
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
if n == 0 {
|
||||||
|
n = sel.PrevFilteredUntilNodes("p", nodes...).Length()
|
||||||
|
} else {
|
||||||
|
sel.PrevFilteredUntilNodes("p", nodes...)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
b.Logf("PrevFilteredUntilNodes=%d", n)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkClosest(b *testing.B) {
|
||||||
|
var n int
|
||||||
|
|
||||||
|
b.StopTimer()
|
||||||
|
sel := Doc().Find(".container-fluid")
|
||||||
|
b.StartTimer()
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
if n == 0 {
|
||||||
|
n = sel.Closest(".pvk-content").Length()
|
||||||
|
} else {
|
||||||
|
sel.Closest(".pvk-content")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
b.Logf("Closest=%d", n)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkClosestSelection(b *testing.B) {
|
||||||
|
var n int
|
||||||
|
|
||||||
|
b.StopTimer()
|
||||||
|
sel := Doc().Find(".container-fluid")
|
||||||
|
sel2 := Doc().Find(".pvk-content")
|
||||||
|
b.StartTimer()
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
if n == 0 {
|
||||||
|
n = sel.ClosestSelection(sel2).Length()
|
||||||
|
} else {
|
||||||
|
sel.ClosestSelection(sel2)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
b.Logf("ClosestSelection=%d", n)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkClosestNodes(b *testing.B) {
|
||||||
|
var n int
|
||||||
|
|
||||||
|
b.StopTimer()
|
||||||
|
sel := Doc().Find(".container-fluid")
|
||||||
|
nodes := Doc().Find(".pvk-content").Nodes
|
||||||
|
b.StartTimer()
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
if n == 0 {
|
||||||
|
n = sel.ClosestNodes(nodes...).Length()
|
||||||
|
} else {
|
||||||
|
sel.ClosestNodes(nodes...)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
b.Logf("ClosestNodes=%d", n)
|
||||||
|
}
|
118
Godeps/_workspace/src/github.com/PuerkitoBio/goquery/doc.go
generated
vendored
Normal file
118
Godeps/_workspace/src/github.com/PuerkitoBio/goquery/doc.go
generated
vendored
Normal file
|
@ -0,0 +1,118 @@
|
||||||
|
// Copyright (c) 2012-2014, Martin Angers & Contributors
|
||||||
|
// All rights reserved.
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without modification,
|
||||||
|
// are permitted provided that the following conditions are met:
|
||||||
|
//
|
||||||
|
// * Redistributions of source code must retain the above copyright notice,
|
||||||
|
// this list of conditions and the following disclaimer.
|
||||||
|
// * Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
// this list of conditions and the following disclaimer in the documentation and/or
|
||||||
|
// other materials provided with the distribution.
|
||||||
|
// * Neither the name of the author nor the names of its contributors may be used to
|
||||||
|
// endorse or promote products derived from this software without specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS
|
||||||
|
// OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||||
|
// AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
|
||||||
|
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||||
|
// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
|
||||||
|
// WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
/*
|
||||||
|
Package goquery implements features similar to jQuery, including the chainable
|
||||||
|
syntax, to manipulate and query an HTML document.
|
||||||
|
|
||||||
|
It brings a syntax and a set of features similar to jQuery to the Go language.
|
||||||
|
It is based on Go's net/html package and the CSS Selector library cascadia.
|
||||||
|
Since the net/html parser returns nodes, and not a full-featured DOM
|
||||||
|
tree, jQuery's stateful manipulation functions (like height(), css(), detach())
|
||||||
|
have been left off.
|
||||||
|
|
||||||
|
Also, because the net/html parser requires UTF-8 encoding, so does goquery: it is
|
||||||
|
the caller's responsibility to ensure that the source document provides UTF-8 encoded HTML.
|
||||||
|
See the repository's wiki for various options on how to do this.
|
||||||
|
|
||||||
|
Syntax-wise, it is as close as possible to jQuery, with the same function names when
|
||||||
|
possible, and that warm and fuzzy chainable interface. jQuery being the
|
||||||
|
ultra-popular library that it is, writing a similar HTML-manipulating
|
||||||
|
library was better to follow its API than to start anew (in the same spirit as
|
||||||
|
Go's fmt package), even though some of its methods are less than intuitive (looking
|
||||||
|
at you, index()...).
|
||||||
|
|
||||||
|
It is hosted on GitHub, along with additional documentation in the README.md
|
||||||
|
file: https://github.com/puerkitobio/goquery
|
||||||
|
|
||||||
|
Please note that because of the net/html dependency, goquery requires Go1.1+.
|
||||||
|
|
||||||
|
The various methods are split into files based on the category of behavior.
|
||||||
|
The three dots (...) indicate that various "overloads" are available.
|
||||||
|
|
||||||
|
* array.go : array-like positional manipulation of the selection.
|
||||||
|
- Eq()
|
||||||
|
- First()
|
||||||
|
- Get()
|
||||||
|
- Index...()
|
||||||
|
- Last()
|
||||||
|
- Slice()
|
||||||
|
|
||||||
|
* expand.go : methods that expand or augment the selection's set.
|
||||||
|
- Add...()
|
||||||
|
- AndSelf()
|
||||||
|
- Union(), which is an alias for AddSelection()
|
||||||
|
|
||||||
|
* filter.go : filtering methods, that reduce the selection's set.
|
||||||
|
- End()
|
||||||
|
- Filter...()
|
||||||
|
- Has...()
|
||||||
|
- Intersection(), which is an alias of FilterSelection()
|
||||||
|
- Not...()
|
||||||
|
|
||||||
|
* iteration.go : methods to loop over the selection's nodes.
|
||||||
|
- Each()
|
||||||
|
- EachWithBreak()
|
||||||
|
- Map()
|
||||||
|
|
||||||
|
* manipulation.go : methods for modifying the document
|
||||||
|
- After...()
|
||||||
|
- Append...()
|
||||||
|
- Before...()
|
||||||
|
- Clone()
|
||||||
|
- Empty()
|
||||||
|
- Prepend...()
|
||||||
|
- Remove...()
|
||||||
|
- ReplaceWith...()
|
||||||
|
- Unwrap()
|
||||||
|
- Wrap...()
|
||||||
|
- WrapAll...()
|
||||||
|
- WrapInner...()
|
||||||
|
|
||||||
|
* property.go : methods that inspect and get the node's properties values.
|
||||||
|
- Attr*(), RemoveAttr(), SetAttr()
|
||||||
|
- AddClass(), HasClass(), RemoveClass(), ToggleClass()
|
||||||
|
- Html()
|
||||||
|
- Length()
|
||||||
|
- Size(), which is an alias for Length()
|
||||||
|
- Text()
|
||||||
|
|
||||||
|
* query.go : methods that query, or reflect, a node's identity.
|
||||||
|
- Contains()
|
||||||
|
- Is...()
|
||||||
|
|
||||||
|
* traversal.go : methods to traverse the HTML document tree.
|
||||||
|
- Children...()
|
||||||
|
- Contents()
|
||||||
|
- Find...()
|
||||||
|
- Next...()
|
||||||
|
- Parent[s]...()
|
||||||
|
- Prev...()
|
||||||
|
- Siblings...()
|
||||||
|
|
||||||
|
* type.go : definition of the types exposed by goquery.
|
||||||
|
- Document
|
||||||
|
- Selection
|
||||||
|
- Matcher
|
||||||
|
*/
|
||||||
|
package goquery
|
68
Godeps/_workspace/src/github.com/PuerkitoBio/goquery/doc/tips.md
generated
vendored
Normal file
68
Godeps/_workspace/src/github.com/PuerkitoBio/goquery/doc/tips.md
generated
vendored
Normal file
|
@ -0,0 +1,68 @@
|
||||||
|
# Tips and tricks
|
||||||
|
|
||||||
|
## Handle Non-UTF8 html Pages
|
||||||
|
|
||||||
|
The `go.net/html` package used by `goquery` requires that the html document is UTF-8 encoded. When you know the encoding of the html page is not UTF-8, you can use the `iconv` package to convert it to UTF-8 (there are various implementation of the `iconv` API, see [godoc.org][iconv] for other options):
|
||||||
|
|
||||||
|
```
|
||||||
|
$ go get -u github.com/djimenez/iconv-go
|
||||||
|
```
|
||||||
|
|
||||||
|
and then:
|
||||||
|
|
||||||
|
```
|
||||||
|
// Load the URL
|
||||||
|
res, err := http.Get(url)
|
||||||
|
if e != nil {
|
||||||
|
// handle error
|
||||||
|
}
|
||||||
|
defer res.Body.Close()
|
||||||
|
|
||||||
|
// Convert the designated charset HTML to utf-8 encoded HTML.
|
||||||
|
// `charset` being one of the charsets known by the iconv package.
|
||||||
|
utfBody, err := iconv.NewReader(res.Body, charset, "utf-8")
|
||||||
|
if err != nil {
|
||||||
|
// handler error
|
||||||
|
}
|
||||||
|
|
||||||
|
// use utfBody using goquery
|
||||||
|
doc, err := goquery.NewDocumentFromReader(utfBody)
|
||||||
|
if err != nil {
|
||||||
|
// handler error
|
||||||
|
}
|
||||||
|
// use doc...
|
||||||
|
```
|
||||||
|
|
||||||
|
Thanks to github user @YuheiNakasaka.
|
||||||
|
|
||||||
|
Actually, the official go.text repository covers this use case too, see its [godoc page][text] for the details.
|
||||||
|
|
||||||
|
|
||||||
|
## Handle Javascript-based Pages
|
||||||
|
|
||||||
|
`goquery` is great to handle normal html pages, but when most of the page is build dynamically using javascript, there's not much it can do. There are various options when faced with this problem:
|
||||||
|
|
||||||
|
* Use a headless browser such as [webloop][].
|
||||||
|
* Use a Go javascript parser package, such as [otto][].
|
||||||
|
|
||||||
|
You can find a code example using `otto` [in this gist][exotto]. Thanks to github user @cryptix.
|
||||||
|
|
||||||
|
## For Loop
|
||||||
|
|
||||||
|
If all you need is a normal `for` loop over all nodes in the current selection, where `Map/Each`-style iteration is not necessary, you can use the following:
|
||||||
|
|
||||||
|
```
|
||||||
|
sel := Doc().Find(".selector")
|
||||||
|
for i := range sel.Nodes {
|
||||||
|
single := sel.Eq(i)
|
||||||
|
// use `single` as a selection of 1 node
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Thanks to github user @jmoiron.
|
||||||
|
|
||||||
|
[webloop]: https://github.com/sourcegraph/webloop
|
||||||
|
[otto]: https://github.com/robertkrimen/otto
|
||||||
|
[exotto]: https://gist.github.com/cryptix/87127f76a94183747b53
|
||||||
|
[iconv]: http://godoc.org/?q=iconv
|
||||||
|
[text]: http://godoc.org/code.google.com/p/go.text/encoding
|
32
Godeps/_workspace/src/github.com/PuerkitoBio/goquery/example_test.go
generated
vendored
Normal file
32
Godeps/_workspace/src/github.com/PuerkitoBio/goquery/example_test.go
generated
vendored
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
package goquery
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"log"
|
||||||
|
|
||||||
|
// In real use, this import would be required (not in this example, since it
|
||||||
|
// is part of the goquery package)
|
||||||
|
//"github.com/PuerkitoBio/goquery"
|
||||||
|
)
|
||||||
|
|
||||||
|
// This example scrapes the reviews shown on the home page of metalsucks.net.
|
||||||
|
func ExampleScrape_MetalSucks() {
|
||||||
|
// Load the HTML document (in real use, the type would be *goquery.Document)
|
||||||
|
doc, err := NewDocument("http://metalsucks.net")
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Find the review items (the type of the Selection would be *goquery.Selection)
|
||||||
|
doc.Find(".reviews-wrap article .review-rhs").Each(func(i int, s *Selection) {
|
||||||
|
// For each item found, get the band and title
|
||||||
|
band := s.Find("h3").Text()
|
||||||
|
title := s.Find("i").Text()
|
||||||
|
fmt.Printf("Review %d: %s - %s\n", i, band, title)
|
||||||
|
})
|
||||||
|
// To see the output of the Example while running the test suite (go test), simply
|
||||||
|
// remove the leading "x" before Output on the next line. This will cause the
|
||||||
|
// example to fail (all the "real" tests should pass).
|
||||||
|
|
||||||
|
// xOutput: voluntarily fail the Example output.
|
||||||
|
}
|
49
Godeps/_workspace/src/github.com/PuerkitoBio/goquery/expand.go
generated
vendored
Normal file
49
Godeps/_workspace/src/github.com/PuerkitoBio/goquery/expand.go
generated
vendored
Normal file
|
@ -0,0 +1,49 @@
|
||||||
|
package goquery
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/andybalholm/cascadia"
|
||||||
|
"golang.org/x/net/html"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Add adds the selector string's matching nodes to those in the current
|
||||||
|
// selection and returns a new Selection object.
|
||||||
|
// The selector string is run in the context of the document of the current
|
||||||
|
// Selection object.
|
||||||
|
func (s *Selection) Add(selector string) *Selection {
|
||||||
|
return s.AddNodes(findWithMatcher([]*html.Node{s.document.rootNode}, cascadia.MustCompile(selector))...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddMatcher adds the matcher's matching nodes to those in the current
|
||||||
|
// selection and returns a new Selection object.
|
||||||
|
// The matcher is run in the context of the document of the current
|
||||||
|
// Selection object.
|
||||||
|
func (s *Selection) AddMatcher(m Matcher) *Selection {
|
||||||
|
return s.AddNodes(findWithMatcher([]*html.Node{s.document.rootNode}, m)...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddSelection adds the specified Selection object's nodes to those in the
|
||||||
|
// current selection and returns a new Selection object.
|
||||||
|
func (s *Selection) AddSelection(sel *Selection) *Selection {
|
||||||
|
if sel == nil {
|
||||||
|
return s.AddNodes()
|
||||||
|
}
|
||||||
|
return s.AddNodes(sel.Nodes...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Union is an alias for AddSelection.
|
||||||
|
func (s *Selection) Union(sel *Selection) *Selection {
|
||||||
|
return s.AddSelection(sel)
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddNodes adds the specified nodes to those in the
|
||||||
|
// current selection and returns a new Selection object.
|
||||||
|
func (s *Selection) AddNodes(nodes ...*html.Node) *Selection {
|
||||||
|
return pushStack(s, appendWithoutDuplicates(s.Nodes, nodes))
|
||||||
|
}
|
||||||
|
|
||||||
|
// AndSelf adds the previous set of elements on the stack to the current set.
|
||||||
|
// It returns a new Selection object containing the current Selection combined
|
||||||
|
// with the previous one.
|
||||||
|
func (s *Selection) AndSelf() *Selection {
|
||||||
|
return s.AddSelection(s.prevSel)
|
||||||
|
}
|
68
Godeps/_workspace/src/github.com/PuerkitoBio/goquery/expand_test.go
generated
vendored
Normal file
68
Godeps/_workspace/src/github.com/PuerkitoBio/goquery/expand_test.go
generated
vendored
Normal file
|
@ -0,0 +1,68 @@
|
||||||
|
package goquery
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestAdd(t *testing.T) {
|
||||||
|
sel := Doc().Find("div.row-fluid").Add("a")
|
||||||
|
assertLength(t, sel.Nodes, 19)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestAddRollback(t *testing.T) {
|
||||||
|
sel := Doc().Find(".pvk-content")
|
||||||
|
sel2 := sel.Add("a").End()
|
||||||
|
assertEqual(t, sel, sel2)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestAddSelection(t *testing.T) {
|
||||||
|
sel := Doc().Find("div.row-fluid")
|
||||||
|
sel2 := Doc().Find("a")
|
||||||
|
sel = sel.AddSelection(sel2)
|
||||||
|
assertLength(t, sel.Nodes, 19)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestAddSelectionNil(t *testing.T) {
|
||||||
|
sel := Doc().Find("div.row-fluid")
|
||||||
|
assertLength(t, sel.Nodes, 9)
|
||||||
|
|
||||||
|
sel = sel.AddSelection(nil)
|
||||||
|
assertLength(t, sel.Nodes, 9)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestAddSelectionRollback(t *testing.T) {
|
||||||
|
sel := Doc().Find(".pvk-content")
|
||||||
|
sel2 := sel.Find("a")
|
||||||
|
sel2 = sel.AddSelection(sel2).End()
|
||||||
|
assertEqual(t, sel, sel2)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestAddNodes(t *testing.T) {
|
||||||
|
sel := Doc().Find("div.pvk-gutter")
|
||||||
|
sel2 := Doc().Find(".pvk-content")
|
||||||
|
sel = sel.AddNodes(sel2.Nodes...)
|
||||||
|
assertLength(t, sel.Nodes, 9)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestAddNodesNone(t *testing.T) {
|
||||||
|
sel := Doc().Find("div.pvk-gutter").AddNodes()
|
||||||
|
assertLength(t, sel.Nodes, 6)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestAddNodesRollback(t *testing.T) {
|
||||||
|
sel := Doc().Find(".pvk-content")
|
||||||
|
sel2 := sel.Find("a")
|
||||||
|
sel2 = sel.AddNodes(sel2.Nodes...).End()
|
||||||
|
assertEqual(t, sel, sel2)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestAndSelf(t *testing.T) {
|
||||||
|
sel := Doc().Find(".span12").Last().AndSelf()
|
||||||
|
assertLength(t, sel.Nodes, 2)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestAndSelfRollback(t *testing.T) {
|
||||||
|
sel := Doc().Find(".pvk-content")
|
||||||
|
sel2 := sel.Find("a").AndSelf().End().End()
|
||||||
|
assertEqual(t, sel, sel2)
|
||||||
|
}
|
156
Godeps/_workspace/src/github.com/PuerkitoBio/goquery/filter.go
generated
vendored
Normal file
156
Godeps/_workspace/src/github.com/PuerkitoBio/goquery/filter.go
generated
vendored
Normal file
|
@ -0,0 +1,156 @@
|
||||||
|
package goquery
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/andybalholm/cascadia"
|
||||||
|
"golang.org/x/net/html"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Filter reduces the set of matched elements to those that match the selector string.
|
||||||
|
// It returns a new Selection object for this subset of matching elements.
|
||||||
|
func (s *Selection) Filter(selector string) *Selection {
|
||||||
|
return s.FilterMatcher(cascadia.MustCompile(selector))
|
||||||
|
}
|
||||||
|
|
||||||
|
// FilterMatcher reduces the set of matched elements to those that match
|
||||||
|
// the given matcher.
|
||||||
|
// It returns a new Selection object for this subset of matching elements.
|
||||||
|
func (s *Selection) FilterMatcher(m Matcher) *Selection {
|
||||||
|
return pushStack(s, winnow(s, m, true))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Not removes elements from the Selection that match the selector string.
|
||||||
|
// It returns a new Selection object with the matching elements removed.
|
||||||
|
func (s *Selection) Not(selector string) *Selection {
|
||||||
|
return s.NotMatcher(cascadia.MustCompile(selector))
|
||||||
|
}
|
||||||
|
|
||||||
|
// NotMatcher removes elements from the Selection that match the given matcher.
|
||||||
|
// It returns a new Selection object with the matching elements removed.
|
||||||
|
func (s *Selection) NotMatcher(m Matcher) *Selection {
|
||||||
|
return pushStack(s, winnow(s, m, false))
|
||||||
|
}
|
||||||
|
|
||||||
|
// FilterFunction reduces the set of matched elements to those that pass the function's test.
|
||||||
|
// It returns a new Selection object for this subset of elements.
|
||||||
|
func (s *Selection) FilterFunction(f func(int, *Selection) bool) *Selection {
|
||||||
|
return pushStack(s, winnowFunction(s, f, true))
|
||||||
|
}
|
||||||
|
|
||||||
|
// NotFunction removes elements from the Selection that pass the function's test.
|
||||||
|
// It returns a new Selection object with the matching elements removed.
|
||||||
|
func (s *Selection) NotFunction(f func(int, *Selection) bool) *Selection {
|
||||||
|
return pushStack(s, winnowFunction(s, f, false))
|
||||||
|
}
|
||||||
|
|
||||||
|
// FilterNodes reduces the set of matched elements to those that match the specified nodes.
|
||||||
|
// It returns a new Selection object for this subset of elements.
|
||||||
|
func (s *Selection) FilterNodes(nodes ...*html.Node) *Selection {
|
||||||
|
return pushStack(s, winnowNodes(s, nodes, true))
|
||||||
|
}
|
||||||
|
|
||||||
|
// NotNodes removes elements from the Selection that match the specified nodes.
|
||||||
|
// It returns a new Selection object with the matching elements removed.
|
||||||
|
func (s *Selection) NotNodes(nodes ...*html.Node) *Selection {
|
||||||
|
return pushStack(s, winnowNodes(s, nodes, false))
|
||||||
|
}
|
||||||
|
|
||||||
|
// FilterSelection reduces the set of matched elements to those that match a
|
||||||
|
// node in the specified Selection object.
|
||||||
|
// It returns a new Selection object for this subset of elements.
|
||||||
|
func (s *Selection) FilterSelection(sel *Selection) *Selection {
|
||||||
|
if sel == nil {
|
||||||
|
return pushStack(s, winnowNodes(s, nil, true))
|
||||||
|
}
|
||||||
|
return pushStack(s, winnowNodes(s, sel.Nodes, true))
|
||||||
|
}
|
||||||
|
|
||||||
|
// NotSelection removes elements from the Selection that match a node in the specified
|
||||||
|
// Selection object. It returns a new Selection object with the matching elements removed.
|
||||||
|
func (s *Selection) NotSelection(sel *Selection) *Selection {
|
||||||
|
if sel == nil {
|
||||||
|
return pushStack(s, winnowNodes(s, nil, false))
|
||||||
|
}
|
||||||
|
return pushStack(s, winnowNodes(s, sel.Nodes, false))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Intersection is an alias for FilterSelection.
|
||||||
|
func (s *Selection) Intersection(sel *Selection) *Selection {
|
||||||
|
return s.FilterSelection(sel)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Has reduces the set of matched elements to those that have a descendant
|
||||||
|
// that matches the selector.
|
||||||
|
// It returns a new Selection object with the matching elements.
|
||||||
|
func (s *Selection) Has(selector string) *Selection {
|
||||||
|
return s.HasSelection(s.document.Find(selector))
|
||||||
|
}
|
||||||
|
|
||||||
|
// HasMatcher reduces the set of matched elements to those that have a descendant
|
||||||
|
// that matches the matcher.
|
||||||
|
// It returns a new Selection object with the matching elements.
|
||||||
|
func (s *Selection) HasMatcher(m Matcher) *Selection {
|
||||||
|
return s.HasSelection(s.document.FindMatcher(m))
|
||||||
|
}
|
||||||
|
|
||||||
|
// HasNodes reduces the set of matched elements to those that have a
|
||||||
|
// descendant that matches one of the nodes.
|
||||||
|
// It returns a new Selection object with the matching elements.
|
||||||
|
func (s *Selection) HasNodes(nodes ...*html.Node) *Selection {
|
||||||
|
return s.FilterFunction(func(_ int, sel *Selection) bool {
|
||||||
|
// Add all nodes that contain one of the specified nodes
|
||||||
|
for _, n := range nodes {
|
||||||
|
if sel.Contains(n) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// HasSelection reduces the set of matched elements to those that have a
|
||||||
|
// descendant that matches one of the nodes of the specified Selection object.
|
||||||
|
// It returns a new Selection object with the matching elements.
|
||||||
|
func (s *Selection) HasSelection(sel *Selection) *Selection {
|
||||||
|
if sel == nil {
|
||||||
|
return s.HasNodes()
|
||||||
|
}
|
||||||
|
return s.HasNodes(sel.Nodes...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// End ends the most recent filtering operation in the current chain and
|
||||||
|
// returns the set of matched elements to its previous state.
|
||||||
|
func (s *Selection) End() *Selection {
|
||||||
|
if s.prevSel != nil {
|
||||||
|
return s.prevSel
|
||||||
|
}
|
||||||
|
return newEmptySelection(s.document)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Filter based on the matcher, and the indicator to keep (Filter) or
|
||||||
|
// to get rid of (Not) the matching elements.
|
||||||
|
func winnow(sel *Selection, m Matcher, keep bool) []*html.Node {
|
||||||
|
// Optimize if keep is requested
|
||||||
|
if keep {
|
||||||
|
return m.Filter(sel.Nodes)
|
||||||
|
}
|
||||||
|
// Use grep
|
||||||
|
return grep(sel, func(i int, s *Selection) bool {
|
||||||
|
return !m.Match(s.Get(0))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// Filter based on an array of nodes, and the indicator to keep (Filter) or
|
||||||
|
// to get rid of (Not) the matching elements.
|
||||||
|
func winnowNodes(sel *Selection, nodes []*html.Node, keep bool) []*html.Node {
|
||||||
|
return grep(sel, func(i int, s *Selection) bool {
|
||||||
|
return isInSlice(nodes, s.Get(0)) == keep
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// Filter based on a function test, and the indicator to keep (Filter) or
|
||||||
|
// to get rid of (Not) the matching elements.
|
||||||
|
func winnowFunction(sel *Selection, f func(int, *Selection) bool, keep bool) []*html.Node {
|
||||||
|
return grep(sel, func(i int, s *Selection) bool {
|
||||||
|
return f(i, s) == keep
|
||||||
|
})
|
||||||
|
}
|
191
Godeps/_workspace/src/github.com/PuerkitoBio/goquery/filter_test.go
generated
vendored
Normal file
191
Godeps/_workspace/src/github.com/PuerkitoBio/goquery/filter_test.go
generated
vendored
Normal file
|
@ -0,0 +1,191 @@
|
||||||
|
package goquery
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestFilter(t *testing.T) {
|
||||||
|
sel := Doc().Find(".span12").Filter(".alert")
|
||||||
|
assertLength(t, sel.Nodes, 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestFilterNone(t *testing.T) {
|
||||||
|
sel := Doc().Find(".span12").Filter(".zzalert")
|
||||||
|
assertLength(t, sel.Nodes, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestFilterRollback(t *testing.T) {
|
||||||
|
sel := Doc().Find(".pvk-content")
|
||||||
|
sel2 := sel.Filter(".alert").End()
|
||||||
|
assertEqual(t, sel, sel2)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestFilterFunction(t *testing.T) {
|
||||||
|
sel := Doc().Find(".pvk-content").FilterFunction(func(i int, s *Selection) bool {
|
||||||
|
return i > 0
|
||||||
|
})
|
||||||
|
assertLength(t, sel.Nodes, 2)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestFilterFunctionRollback(t *testing.T) {
|
||||||
|
sel := Doc().Find(".pvk-content")
|
||||||
|
sel2 := sel.FilterFunction(func(i int, s *Selection) bool {
|
||||||
|
return i > 0
|
||||||
|
}).End()
|
||||||
|
assertEqual(t, sel, sel2)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestFilterNode(t *testing.T) {
|
||||||
|
sel := Doc().Find(".pvk-content")
|
||||||
|
sel2 := sel.FilterNodes(sel.Nodes[2])
|
||||||
|
assertLength(t, sel2.Nodes, 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestFilterNodeRollback(t *testing.T) {
|
||||||
|
sel := Doc().Find(".pvk-content")
|
||||||
|
sel2 := sel.FilterNodes(sel.Nodes[2]).End()
|
||||||
|
assertEqual(t, sel, sel2)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestFilterSelection(t *testing.T) {
|
||||||
|
sel := Doc().Find(".link")
|
||||||
|
sel2 := Doc().Find("a[ng-click]")
|
||||||
|
sel3 := sel.FilterSelection(sel2)
|
||||||
|
assertLength(t, sel3.Nodes, 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestFilterSelectionRollback(t *testing.T) {
|
||||||
|
sel := Doc().Find(".link")
|
||||||
|
sel2 := Doc().Find("a[ng-click]")
|
||||||
|
sel2 = sel.FilterSelection(sel2).End()
|
||||||
|
assertEqual(t, sel, sel2)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestFilterSelectionNil(t *testing.T) {
|
||||||
|
var sel2 *Selection
|
||||||
|
|
||||||
|
sel := Doc().Find(".link")
|
||||||
|
sel3 := sel.FilterSelection(sel2)
|
||||||
|
assertLength(t, sel3.Nodes, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestNot(t *testing.T) {
|
||||||
|
sel := Doc().Find(".span12").Not(".alert")
|
||||||
|
assertLength(t, sel.Nodes, 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestNotRollback(t *testing.T) {
|
||||||
|
sel := Doc().Find(".span12")
|
||||||
|
sel2 := sel.Not(".alert").End()
|
||||||
|
assertEqual(t, sel, sel2)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestNotNone(t *testing.T) {
|
||||||
|
sel := Doc().Find(".span12").Not(".zzalert")
|
||||||
|
assertLength(t, sel.Nodes, 2)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestNotFunction(t *testing.T) {
|
||||||
|
sel := Doc().Find(".pvk-content").NotFunction(func(i int, s *Selection) bool {
|
||||||
|
return i > 0
|
||||||
|
})
|
||||||
|
assertLength(t, sel.Nodes, 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestNotFunctionRollback(t *testing.T) {
|
||||||
|
sel := Doc().Find(".pvk-content")
|
||||||
|
sel2 := sel.NotFunction(func(i int, s *Selection) bool {
|
||||||
|
return i > 0
|
||||||
|
}).End()
|
||||||
|
assertEqual(t, sel, sel2)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestNotNode(t *testing.T) {
|
||||||
|
sel := Doc().Find(".pvk-content")
|
||||||
|
sel2 := sel.NotNodes(sel.Nodes[2])
|
||||||
|
assertLength(t, sel2.Nodes, 2)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestNotNodeRollback(t *testing.T) {
|
||||||
|
sel := Doc().Find(".pvk-content")
|
||||||
|
sel2 := sel.NotNodes(sel.Nodes[2]).End()
|
||||||
|
assertEqual(t, sel, sel2)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestNotSelection(t *testing.T) {
|
||||||
|
sel := Doc().Find(".link")
|
||||||
|
sel2 := Doc().Find("a[ng-click]")
|
||||||
|
sel3 := sel.NotSelection(sel2)
|
||||||
|
assertLength(t, sel3.Nodes, 6)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestNotSelectionRollback(t *testing.T) {
|
||||||
|
sel := Doc().Find(".link")
|
||||||
|
sel2 := Doc().Find("a[ng-click]")
|
||||||
|
sel2 = sel.NotSelection(sel2).End()
|
||||||
|
assertEqual(t, sel, sel2)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestIntersection(t *testing.T) {
|
||||||
|
sel := Doc().Find(".pvk-gutter")
|
||||||
|
sel2 := Doc().Find("div").Intersection(sel)
|
||||||
|
assertLength(t, sel2.Nodes, 6)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestIntersectionRollback(t *testing.T) {
|
||||||
|
sel := Doc().Find(".pvk-gutter")
|
||||||
|
sel2 := Doc().Find("div")
|
||||||
|
sel2 = sel.Intersection(sel2).End()
|
||||||
|
assertEqual(t, sel, sel2)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestHas(t *testing.T) {
|
||||||
|
sel := Doc().Find(".container-fluid").Has(".center-content")
|
||||||
|
assertLength(t, sel.Nodes, 2)
|
||||||
|
// Has() returns the high-level .container-fluid div, and the one that is the immediate parent of center-content
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestHasRollback(t *testing.T) {
|
||||||
|
sel := Doc().Find(".container-fluid")
|
||||||
|
sel2 := sel.Has(".center-content").End()
|
||||||
|
assertEqual(t, sel, sel2)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestHasNodes(t *testing.T) {
|
||||||
|
sel := Doc().Find(".container-fluid")
|
||||||
|
sel2 := Doc().Find(".center-content")
|
||||||
|
sel = sel.HasNodes(sel2.Nodes...)
|
||||||
|
assertLength(t, sel.Nodes, 2)
|
||||||
|
// Has() returns the high-level .container-fluid div, and the one that is the immediate parent of center-content
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestHasNodesRollback(t *testing.T) {
|
||||||
|
sel := Doc().Find(".container-fluid")
|
||||||
|
sel2 := Doc().Find(".center-content")
|
||||||
|
sel2 = sel.HasNodes(sel2.Nodes...).End()
|
||||||
|
assertEqual(t, sel, sel2)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestHasSelection(t *testing.T) {
|
||||||
|
sel := Doc().Find("p")
|
||||||
|
sel2 := Doc().Find("small")
|
||||||
|
sel = sel.HasSelection(sel2)
|
||||||
|
assertLength(t, sel.Nodes, 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestHasSelectionRollback(t *testing.T) {
|
||||||
|
sel := Doc().Find("p")
|
||||||
|
sel2 := Doc().Find("small")
|
||||||
|
sel2 = sel.HasSelection(sel2).End()
|
||||||
|
assertEqual(t, sel, sel2)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestEnd(t *testing.T) {
|
||||||
|
sel := Doc().Find("p").Has("small").End()
|
||||||
|
assertLength(t, sel.Nodes, 4)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestEndToTop(t *testing.T) {
|
||||||
|
sel := Doc().Find("p").Has("small").End().End().End()
|
||||||
|
assertLength(t, sel.Nodes, 0)
|
||||||
|
}
|
33
Godeps/_workspace/src/github.com/PuerkitoBio/goquery/iteration.go
generated
vendored
Normal file
33
Godeps/_workspace/src/github.com/PuerkitoBio/goquery/iteration.go
generated
vendored
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
package goquery
|
||||||
|
|
||||||
|
// Each iterates over a Selection object, executing a function for each
|
||||||
|
// matched element. It returns the current Selection object.
|
||||||
|
func (s *Selection) Each(f func(int, *Selection)) *Selection {
|
||||||
|
for i, n := range s.Nodes {
|
||||||
|
f(i, newSingleSelection(n, s.document))
|
||||||
|
}
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
|
||||||
|
// EachWithBreak iterates over a Selection object, executing a function for each
|
||||||
|
// matched element. It is identical to Each except that it is possible to break
|
||||||
|
// out of the loop by returning false in the callback function. It returns the
|
||||||
|
// current Selection object.
|
||||||
|
func (s *Selection) EachWithBreak(f func(int, *Selection) bool) *Selection {
|
||||||
|
for i, n := range s.Nodes {
|
||||||
|
if !f(i, newSingleSelection(n, s.document)) {
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
|
||||||
|
// Map passes each element in the current matched set through a function,
|
||||||
|
// producing a slice of string holding the returned values.
|
||||||
|
func (s *Selection) Map(f func(int, *Selection) string) (result []string) {
|
||||||
|
for i, n := range s.Nodes {
|
||||||
|
result = append(result, f(i, newSingleSelection(n, s.document)))
|
||||||
|
}
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
88
Godeps/_workspace/src/github.com/PuerkitoBio/goquery/iteration_test.go
generated
vendored
Normal file
88
Godeps/_workspace/src/github.com/PuerkitoBio/goquery/iteration_test.go
generated
vendored
Normal file
|
@ -0,0 +1,88 @@
|
||||||
|
package goquery
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"golang.org/x/net/html"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestEach(t *testing.T) {
|
||||||
|
var cnt int
|
||||||
|
|
||||||
|
sel := Doc().Find(".hero-unit .row-fluid").Each(func(i int, n *Selection) {
|
||||||
|
cnt++
|
||||||
|
t.Logf("At index %v, node %v", i, n.Nodes[0].Data)
|
||||||
|
}).Find("a")
|
||||||
|
|
||||||
|
if cnt != 4 {
|
||||||
|
t.Errorf("Expected Each() to call function 4 times, got %v times.", cnt)
|
||||||
|
}
|
||||||
|
assertLength(t, sel.Nodes, 6)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestEachWithBreak(t *testing.T) {
|
||||||
|
var cnt int
|
||||||
|
|
||||||
|
sel := Doc().Find(".hero-unit .row-fluid").EachWithBreak(func(i int, n *Selection) bool {
|
||||||
|
cnt++
|
||||||
|
t.Logf("At index %v, node %v", i, n.Nodes[0].Data)
|
||||||
|
return false
|
||||||
|
}).Find("a")
|
||||||
|
|
||||||
|
if cnt != 1 {
|
||||||
|
t.Errorf("Expected Each() to call function 1 time, got %v times.", cnt)
|
||||||
|
}
|
||||||
|
assertLength(t, sel.Nodes, 6)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestEachEmptySelection(t *testing.T) {
|
||||||
|
var cnt int
|
||||||
|
|
||||||
|
sel := Doc().Find("zzzz")
|
||||||
|
sel.Each(func(i int, n *Selection) {
|
||||||
|
cnt++
|
||||||
|
})
|
||||||
|
if cnt > 0 {
|
||||||
|
t.Error("Expected Each() to not be called on empty Selection.")
|
||||||
|
}
|
||||||
|
sel2 := sel.Find("div")
|
||||||
|
assertLength(t, sel2.Nodes, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestMap(t *testing.T) {
|
||||||
|
sel := Doc().Find(".pvk-content")
|
||||||
|
vals := sel.Map(func(i int, s *Selection) string {
|
||||||
|
n := s.Get(0)
|
||||||
|
if n.Type == html.ElementNode {
|
||||||
|
return n.Data
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
})
|
||||||
|
for _, v := range vals {
|
||||||
|
if v != "div" {
|
||||||
|
t.Error("Expected Map array result to be all 'div's.")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if len(vals) != 3 {
|
||||||
|
t.Errorf("Expected Map array result to have a length of 3, found %v.", len(vals))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestForRange(t *testing.T) {
|
||||||
|
sel := Doc().Find(".pvk-content")
|
||||||
|
initLen := sel.Length()
|
||||||
|
for i := range sel.Nodes {
|
||||||
|
single := sel.Eq(i)
|
||||||
|
//h, err := single.Html()
|
||||||
|
//if err != nil {
|
||||||
|
// t.Fatal(err)
|
||||||
|
//}
|
||||||
|
//fmt.Println(i, h)
|
||||||
|
if single.Length() != 1 {
|
||||||
|
t.Errorf("%d: expected length of 1, got %d", i, single.Length())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if sel.Length() != initLen {
|
||||||
|
t.Errorf("expected initial selection to still have length %d, got %d", initLen, sel.Length())
|
||||||
|
}
|
||||||
|
}
|
551
Godeps/_workspace/src/github.com/PuerkitoBio/goquery/manipulation.go
generated
vendored
Normal file
551
Godeps/_workspace/src/github.com/PuerkitoBio/goquery/manipulation.go
generated
vendored
Normal file
|
@ -0,0 +1,551 @@
|
||||||
|
package goquery
|
||||||
|
|
||||||
|
import (
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/andybalholm/cascadia"
|
||||||
|
"golang.org/x/net/html"
|
||||||
|
)
|
||||||
|
|
||||||
|
// After applies the selector from the root document and inserts the matched elements
|
||||||
|
// after the elements in the set of matched elements.
|
||||||
|
//
|
||||||
|
// If one of the matched elements in the selection is not currently in the
|
||||||
|
// document, it's impossible to insert nodes after it, so it will be ignored.
|
||||||
|
//
|
||||||
|
// This follows the same rules as Selection.Append.
|
||||||
|
func (s *Selection) After(selector string) *Selection {
|
||||||
|
return s.AfterMatcher(cascadia.MustCompile(selector))
|
||||||
|
}
|
||||||
|
|
||||||
|
// AfterMatcher applies the matcher from the root document and inserts the matched elements
|
||||||
|
// after the elements in the set of matched elements.
|
||||||
|
//
|
||||||
|
// If one of the matched elements in the selection is not currently in the
|
||||||
|
// document, it's impossible to insert nodes after it, so it will be ignored.
|
||||||
|
//
|
||||||
|
// This follows the same rules as Selection.Append.
|
||||||
|
func (s *Selection) AfterMatcher(m Matcher) *Selection {
|
||||||
|
return s.AfterNodes(m.MatchAll(s.document.rootNode)...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// AfterSelection inserts the elements in the selection after each element in the set of matched
|
||||||
|
// elements.
|
||||||
|
//
|
||||||
|
// This follows the same rules as Selection.Append.
|
||||||
|
func (s *Selection) AfterSelection(sel *Selection) *Selection {
|
||||||
|
return s.AfterNodes(sel.Nodes...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// AfterHtml parses the html and inserts it after the set of matched elements.
|
||||||
|
//
|
||||||
|
// This follows the same rules as Selection.Append.
|
||||||
|
func (s *Selection) AfterHtml(html string) *Selection {
|
||||||
|
return s.AfterNodes(parseHtml(html)...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// AfterNodes inserts the nodes after each element in the set of matched elements.
|
||||||
|
//
|
||||||
|
// This follows the same rules as Selection.Append.
|
||||||
|
func (s *Selection) AfterNodes(ns ...*html.Node) *Selection {
|
||||||
|
return s.manipulateNodes(ns, true, func(sn *html.Node, n *html.Node) {
|
||||||
|
if sn.Parent != nil {
|
||||||
|
sn.Parent.InsertBefore(n, sn.NextSibling)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// Append appends the elements specified by the selector to the end of each element
|
||||||
|
// in the set of matched elements, following those rules:
|
||||||
|
//
|
||||||
|
// 1) The selector is applied to the root document.
|
||||||
|
//
|
||||||
|
// 2) Elements that are part of the document will be moved to the new location.
|
||||||
|
//
|
||||||
|
// 3) If there are multiple locations to append to, cloned nodes will be
|
||||||
|
// appended to all target locations except the last one, which will be moved
|
||||||
|
// as noted in (2).
|
||||||
|
func (s *Selection) Append(selector string) *Selection {
|
||||||
|
return s.AppendMatcher(cascadia.MustCompile(selector))
|
||||||
|
}
|
||||||
|
|
||||||
|
// AppendMatcher appends the elements specified by the matcher to the end of each element
|
||||||
|
// in the set of matched elements.
|
||||||
|
//
|
||||||
|
// This follows the same rules as Selection.Append.
|
||||||
|
func (s *Selection) AppendMatcher(m Matcher) *Selection {
|
||||||
|
return s.AppendNodes(m.MatchAll(s.document.rootNode)...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// AppendSelection appends the elements in the selection to the end of each element
|
||||||
|
// in the set of matched elements.
|
||||||
|
//
|
||||||
|
// This follows the same rules as Selection.Append.
|
||||||
|
func (s *Selection) AppendSelection(sel *Selection) *Selection {
|
||||||
|
return s.AppendNodes(sel.Nodes...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// AppendHtml parses the html and appends it to the set of matched elements.
|
||||||
|
func (s *Selection) AppendHtml(html string) *Selection {
|
||||||
|
return s.AppendNodes(parseHtml(html)...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// AppendNodes appends the specified nodes to each node in the set of matched elements.
|
||||||
|
//
|
||||||
|
// This follows the same rules as Selection.Append.
|
||||||
|
func (s *Selection) AppendNodes(ns ...*html.Node) *Selection {
|
||||||
|
return s.manipulateNodes(ns, false, func(sn *html.Node, n *html.Node) {
|
||||||
|
sn.AppendChild(n)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// Before inserts the matched elements before each element in the set of matched elements.
|
||||||
|
//
|
||||||
|
// This follows the same rules as Selection.Append.
|
||||||
|
func (s *Selection) Before(selector string) *Selection {
|
||||||
|
return s.BeforeMatcher(cascadia.MustCompile(selector))
|
||||||
|
}
|
||||||
|
|
||||||
|
// BeforeMatcher inserts the matched elements before each element in the set of matched elements.
|
||||||
|
//
|
||||||
|
// This follows the same rules as Selection.Append.
|
||||||
|
func (s *Selection) BeforeMatcher(m Matcher) *Selection {
|
||||||
|
return s.BeforeNodes(m.MatchAll(s.document.rootNode)...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// BeforeSelection inserts the elements in the selection before each element in the set of matched
|
||||||
|
// elements.
|
||||||
|
//
|
||||||
|
// This follows the same rules as Selection.Append.
|
||||||
|
func (s *Selection) BeforeSelection(sel *Selection) *Selection {
|
||||||
|
return s.BeforeNodes(sel.Nodes...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// BeforeHtml parses the html and inserts it before the set of matched elements.
|
||||||
|
//
|
||||||
|
// This follows the same rules as Selection.Append.
|
||||||
|
func (s *Selection) BeforeHtml(html string) *Selection {
|
||||||
|
return s.BeforeNodes(parseHtml(html)...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// BeforeNodes inserts the nodes before each element in the set of matched elements.
|
||||||
|
//
|
||||||
|
// This follows the same rules as Selection.Append.
|
||||||
|
func (s *Selection) BeforeNodes(ns ...*html.Node) *Selection {
|
||||||
|
return s.manipulateNodes(ns, false, func(sn *html.Node, n *html.Node) {
|
||||||
|
if sn.Parent != nil {
|
||||||
|
sn.Parent.InsertBefore(n, sn)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clone creates a deep copy of the set of matched nodes. The new nodes will not be
|
||||||
|
// attached to the document.
|
||||||
|
func (s *Selection) Clone() *Selection {
|
||||||
|
ns := newEmptySelection(s.document)
|
||||||
|
ns.Nodes = cloneNodes(s.Nodes)
|
||||||
|
return ns
|
||||||
|
}
|
||||||
|
|
||||||
|
// Empty removes all children nodes from the set of matched elements.
|
||||||
|
// It returns the children nodes in a new Selection.
|
||||||
|
func (s *Selection) Empty() *Selection {
|
||||||
|
var nodes []*html.Node
|
||||||
|
|
||||||
|
for _, n := range s.Nodes {
|
||||||
|
for c := n.FirstChild; c != nil; c = n.FirstChild {
|
||||||
|
n.RemoveChild(c)
|
||||||
|
nodes = append(nodes, c)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return pushStack(s, nodes)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Prepend prepends the elements specified by the selector to each element in
|
||||||
|
// the set of matched elements, following the same rules as Append.
|
||||||
|
func (s *Selection) Prepend(selector string) *Selection {
|
||||||
|
return s.PrependMatcher(cascadia.MustCompile(selector))
|
||||||
|
}
|
||||||
|
|
||||||
|
// PrependMatcher prepends the elements specified by the matcher to each
|
||||||
|
// element in the set of matched elements.
|
||||||
|
//
|
||||||
|
// This follows the same rules as Selection.Append.
|
||||||
|
func (s *Selection) PrependMatcher(m Matcher) *Selection {
|
||||||
|
return s.PrependNodes(m.MatchAll(s.document.rootNode)...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// PrependSelection prepends the elements in the selection to each element in
|
||||||
|
// the set of matched elements.
|
||||||
|
//
|
||||||
|
// This follows the same rules as Selection.Append.
|
||||||
|
func (s *Selection) PrependSelection(sel *Selection) *Selection {
|
||||||
|
return s.PrependNodes(sel.Nodes...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// PrependHtml parses the html and prepends it to the set of matched elements.
|
||||||
|
func (s *Selection) PrependHtml(html string) *Selection {
|
||||||
|
return s.PrependNodes(parseHtml(html)...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// PrependNodes prepends the specified nodes to each node in the set of
|
||||||
|
// matched elements.
|
||||||
|
//
|
||||||
|
// This follows the same rules as Selection.Append.
|
||||||
|
func (s *Selection) PrependNodes(ns ...*html.Node) *Selection {
|
||||||
|
return s.manipulateNodes(ns, true, func(sn *html.Node, n *html.Node) {
|
||||||
|
// sn.FirstChild may be nil, in which case this functions like
|
||||||
|
// sn.AppendChild()
|
||||||
|
sn.InsertBefore(n, sn.FirstChild)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove removes the set of matched elements from the document.
|
||||||
|
// It returns the same selection, now consisting of nodes not in the document.
|
||||||
|
func (s *Selection) Remove() *Selection {
|
||||||
|
for _, n := range s.Nodes {
|
||||||
|
if n.Parent != nil {
|
||||||
|
n.Parent.RemoveChild(n)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
|
||||||
|
// RemoveFiltered removes the set of matched elements by selector.
|
||||||
|
// It returns the Selection of removed nodes.
|
||||||
|
func (s *Selection) RemoveFiltered(selector string) *Selection {
|
||||||
|
return s.RemoveMatcher(cascadia.MustCompile(selector))
|
||||||
|
}
|
||||||
|
|
||||||
|
// RemoveMatcher removes the set of matched elements.
|
||||||
|
// It returns the Selection of removed nodes.
|
||||||
|
func (s *Selection) RemoveMatcher(m Matcher) *Selection {
|
||||||
|
return s.FilterMatcher(m).Remove()
|
||||||
|
}
|
||||||
|
|
||||||
|
// ReplaceWith replaces each element in the set of matched elements with the
|
||||||
|
// nodes matched by the given selector.
|
||||||
|
// It returns the removed elements.
|
||||||
|
//
|
||||||
|
// This follows the same rules as Selection.Append.
|
||||||
|
func (s *Selection) ReplaceWith(selector string) *Selection {
|
||||||
|
return s.ReplaceWithMatcher(cascadia.MustCompile(selector))
|
||||||
|
}
|
||||||
|
|
||||||
|
// ReplaceWithMatcher replaces each element in the set of matched elements with
|
||||||
|
// the nodes matched by the given Matcher.
|
||||||
|
// It returns the removed elements.
|
||||||
|
//
|
||||||
|
// This follows the same rules as Selection.Append.
|
||||||
|
func (s *Selection) ReplaceWithMatcher(m Matcher) *Selection {
|
||||||
|
return s.ReplaceWithNodes(m.MatchAll(s.document.rootNode)...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ReplaceWithSelection replaces each element in the set of matched elements with
|
||||||
|
// the nodes from the given Selection.
|
||||||
|
// It returns the removed elements.
|
||||||
|
//
|
||||||
|
// This follows the same rules as Selection.Append.
|
||||||
|
func (s *Selection) ReplaceWithSelection(sel *Selection) *Selection {
|
||||||
|
return s.ReplaceWithNodes(sel.Nodes...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ReplaceWithHtml replaces each element in the set of matched elements with
|
||||||
|
// the parsed HTML.
|
||||||
|
// It returns the removed elements.
|
||||||
|
//
|
||||||
|
// This follows the same rules as Selection.Append.
|
||||||
|
func (s *Selection) ReplaceWithHtml(html string) *Selection {
|
||||||
|
return s.ReplaceWithNodes(parseHtml(html)...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ReplaceWithNodes replaces each element in the set of matched elements with
|
||||||
|
// the given nodes.
|
||||||
|
// It returns the removed elements.
|
||||||
|
//
|
||||||
|
// This follows the same rules as Selection.Append.
|
||||||
|
func (s *Selection) ReplaceWithNodes(ns ...*html.Node) *Selection {
|
||||||
|
s.AfterNodes(ns...)
|
||||||
|
return s.Remove()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Unwrap removes the parents of the set of matched elements, leaving the matched
|
||||||
|
// elements (and their siblings, if any) in their place.
|
||||||
|
// It returns the original selection.
|
||||||
|
func (s *Selection) Unwrap() *Selection {
|
||||||
|
s.Parent().Each(func(i int, ss *Selection) {
|
||||||
|
// For some reason, jquery allows unwrap to remove the <head> element, so
|
||||||
|
// allowing it here too. Same for <html>. Why it allows those elements to
|
||||||
|
// be unwrapped while not allowing body is a mystery to me.
|
||||||
|
if ss.Nodes[0].Data != "body" {
|
||||||
|
ss.ReplaceWithSelection(ss.Contents())
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
|
||||||
|
// Wrap wraps each element in the set of matched elements inside the first
|
||||||
|
// element matched by the given selector. The matched child is cloned before
|
||||||
|
// being inserted into the document.
|
||||||
|
//
|
||||||
|
// It returns the original set of elements.
|
||||||
|
func (s *Selection) Wrap(selector string) *Selection {
|
||||||
|
return s.WrapMatcher(cascadia.MustCompile(selector))
|
||||||
|
}
|
||||||
|
|
||||||
|
// WrapMatcher wraps each element in the set of matched elements inside the
|
||||||
|
// first element matched by the given matcher. The matched child is cloned
|
||||||
|
// before being inserted into the document.
|
||||||
|
//
|
||||||
|
// It returns the original set of elements.
|
||||||
|
func (s *Selection) WrapMatcher(m Matcher) *Selection {
|
||||||
|
return s.wrapNodes(m.MatchAll(s.document.rootNode)...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// WrapSelection wraps each element in the set of matched elements inside the
|
||||||
|
// first element in the given Selection. The element is cloned before being
|
||||||
|
// inserted into the document.
|
||||||
|
//
|
||||||
|
// It returns the original set of elements.
|
||||||
|
func (s *Selection) WrapSelection(sel *Selection) *Selection {
|
||||||
|
return s.wrapNodes(sel.Nodes...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// WrapHtml wraps each element in the set of matched elements inside the inner-
|
||||||
|
// most child of the given HTML.
|
||||||
|
//
|
||||||
|
// It returns the original set of elements.
|
||||||
|
func (s *Selection) WrapHtml(html string) *Selection {
|
||||||
|
return s.wrapNodes(parseHtml(html)...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// WrapNode wraps each element in the set of matched elements inside the inner-
|
||||||
|
// most child of the given node. The given node is copied before being inserted
|
||||||
|
// into the document.
|
||||||
|
//
|
||||||
|
// It returns the original set of elements.
|
||||||
|
func (s *Selection) WrapNode(n *html.Node) *Selection {
|
||||||
|
return s.wrapNodes(n)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Selection) wrapNodes(ns ...*html.Node) *Selection {
|
||||||
|
s.Each(func(i int, ss *Selection) {
|
||||||
|
ss.wrapAllNodes(ns...)
|
||||||
|
})
|
||||||
|
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
|
||||||
|
// WrapAll wraps a single HTML structure, matched by the given selector, around
|
||||||
|
// all elements in the set of matched elements. The matched child is cloned
|
||||||
|
// before being inserted into the document.
|
||||||
|
//
|
||||||
|
// It returns the original set of elements.
|
||||||
|
func (s *Selection) WrapAll(selector string) *Selection {
|
||||||
|
return s.WrapAllMatcher(cascadia.MustCompile(selector))
|
||||||
|
}
|
||||||
|
|
||||||
|
// WrapAllMatcher wraps a single HTML structure, matched by the given Matcher,
|
||||||
|
// around all elements in the set of matched elements. The matched child is
|
||||||
|
// cloned before being inserted into the document.
|
||||||
|
//
|
||||||
|
// It returns the original set of elements.
|
||||||
|
func (s *Selection) WrapAllMatcher(m Matcher) *Selection {
|
||||||
|
return s.wrapAllNodes(m.MatchAll(s.document.rootNode)...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// WrapAllSelection wraps a single HTML structure, the first node of the given
|
||||||
|
// Selection, around all elements in the set of matched elements. The matched
|
||||||
|
// child is cloned before being inserted into the document.
|
||||||
|
//
|
||||||
|
// It returns the original set of elements.
|
||||||
|
func (s *Selection) WrapAllSelection(sel *Selection) *Selection {
|
||||||
|
return s.wrapAllNodes(sel.Nodes...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// WrapAllHtml wraps the given HTML structure around all elements in the set of
|
||||||
|
// matched elements. The matched child is cloned before being inserted into the
|
||||||
|
// document.
|
||||||
|
//
|
||||||
|
// It returns the original set of elements.
|
||||||
|
func (s *Selection) WrapAllHtml(html string) *Selection {
|
||||||
|
return s.wrapAllNodes(parseHtml(html)...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Selection) wrapAllNodes(ns ...*html.Node) *Selection {
|
||||||
|
if len(ns) > 0 {
|
||||||
|
return s.WrapAllNode(ns[0])
|
||||||
|
}
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
|
||||||
|
// WrapAllNode wraps the given node around the first element in the Selection,
|
||||||
|
// making all other nodes in the Selection children of the given node. The node
|
||||||
|
// is cloned before being inserted into the document.
|
||||||
|
//
|
||||||
|
// It returns the original set of elements.
|
||||||
|
func (s *Selection) WrapAllNode(n *html.Node) *Selection {
|
||||||
|
if s.Size() == 0 {
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
|
||||||
|
wrap := cloneNode(n)
|
||||||
|
|
||||||
|
first := s.Nodes[0]
|
||||||
|
if first.Parent != nil {
|
||||||
|
first.Parent.InsertBefore(wrap, first)
|
||||||
|
first.Parent.RemoveChild(first)
|
||||||
|
}
|
||||||
|
|
||||||
|
for c := getFirstChildEl(wrap); c != nil; c = getFirstChildEl(wrap) {
|
||||||
|
wrap = c
|
||||||
|
}
|
||||||
|
|
||||||
|
newSingleSelection(wrap, s.document).AppendSelection(s)
|
||||||
|
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
|
||||||
|
// WrapInner wraps an HTML structure, matched by the given selector, around the
|
||||||
|
// content of element in the set of matched elements. The matched child is
|
||||||
|
// cloned before being inserted into the document.
|
||||||
|
//
|
||||||
|
// It returns the original set of elements.
|
||||||
|
func (s *Selection) WrapInner(selector string) *Selection {
|
||||||
|
return s.WrapInnerMatcher(cascadia.MustCompile(selector))
|
||||||
|
}
|
||||||
|
|
||||||
|
// WrapInnerMatcher wraps an HTML structure, matched by the given selector,
|
||||||
|
// around the content of element in the set of matched elements. The matched
|
||||||
|
// child is cloned before being inserted into the document.
|
||||||
|
//
|
||||||
|
// It returns the original set of elements.
|
||||||
|
func (s *Selection) WrapInnerMatcher(m Matcher) *Selection {
|
||||||
|
return s.wrapInnerNodes(m.MatchAll(s.document.rootNode)...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// WrapInnerSelection wraps an HTML structure, matched by the given selector,
|
||||||
|
// around the content of element in the set of matched elements. The matched
|
||||||
|
// child is cloned before being inserted into the document.
|
||||||
|
//
|
||||||
|
// It returns the original set of elements.
|
||||||
|
func (s *Selection) WrapInnerSelection(sel *Selection) *Selection {
|
||||||
|
return s.wrapInnerNodes(sel.Nodes...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// WrapInnerHtml wraps an HTML structure, matched by the given selector, around
|
||||||
|
// the content of element in the set of matched elements. The matched child is
|
||||||
|
// cloned before being inserted into the document.
|
||||||
|
//
|
||||||
|
// It returns the original set of elements.
|
||||||
|
func (s *Selection) WrapInnerHtml(html string) *Selection {
|
||||||
|
return s.wrapInnerNodes(parseHtml(html)...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// WrapInnerNode wraps an HTML structure, matched by the given selector, around
|
||||||
|
// the content of element in the set of matched elements. The matched child is
|
||||||
|
// cloned before being inserted into the document.
|
||||||
|
//
|
||||||
|
// It returns the original set of elements.
|
||||||
|
func (s *Selection) WrapInnerNode(n *html.Node) *Selection {
|
||||||
|
return s.wrapInnerNodes(n)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Selection) wrapInnerNodes(ns ...*html.Node) *Selection {
|
||||||
|
if len(ns) == 0 {
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
|
||||||
|
s.Each(func(i int, s *Selection) {
|
||||||
|
contents := s.Contents()
|
||||||
|
|
||||||
|
if contents.Size() > 0 {
|
||||||
|
contents.wrapAllNodes(ns...)
|
||||||
|
} else {
|
||||||
|
s.AppendNodes(cloneNode(ns[0]))
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseHtml(h string) []*html.Node {
|
||||||
|
// Errors are only returned when the io.Reader returns any error besides
|
||||||
|
// EOF, but strings.Reader never will
|
||||||
|
nodes, err := html.ParseFragment(strings.NewReader(h), &html.Node{Type: html.ElementNode})
|
||||||
|
if err != nil {
|
||||||
|
panic("goquery: failed to parse HTML: " + err.Error())
|
||||||
|
}
|
||||||
|
return nodes
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the first child that is an ElementNode
|
||||||
|
func getFirstChildEl(n *html.Node) *html.Node {
|
||||||
|
c := n.FirstChild
|
||||||
|
for c != nil && c.Type != html.ElementNode {
|
||||||
|
c = c.NextSibling
|
||||||
|
}
|
||||||
|
return c
|
||||||
|
}
|
||||||
|
|
||||||
|
// Deep copy a slice of nodes.
|
||||||
|
func cloneNodes(ns []*html.Node) []*html.Node {
|
||||||
|
cns := make([]*html.Node, 0, len(ns))
|
||||||
|
|
||||||
|
for _, n := range ns {
|
||||||
|
cns = append(cns, cloneNode(n))
|
||||||
|
}
|
||||||
|
|
||||||
|
return cns
|
||||||
|
}
|
||||||
|
|
||||||
|
// Deep copy a node. The new node has clones of all the original node's
|
||||||
|
// children but none of its parents or siblings.
|
||||||
|
func cloneNode(n *html.Node) *html.Node {
|
||||||
|
nn := &html.Node{
|
||||||
|
Type: n.Type,
|
||||||
|
DataAtom: n.DataAtom,
|
||||||
|
Data: n.Data,
|
||||||
|
Attr: make([]html.Attribute, len(n.Attr)),
|
||||||
|
}
|
||||||
|
|
||||||
|
copy(nn.Attr, n.Attr)
|
||||||
|
for c := n.FirstChild; c != nil; c = c.NextSibling {
|
||||||
|
nn.AppendChild(cloneNode(c))
|
||||||
|
}
|
||||||
|
|
||||||
|
return nn
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Selection) manipulateNodes(ns []*html.Node, reverse bool,
|
||||||
|
f func(sn *html.Node, n *html.Node)) *Selection {
|
||||||
|
|
||||||
|
lasti := s.Size() - 1
|
||||||
|
|
||||||
|
// net.Html doesn't provide document fragments for insertion, so to get
|
||||||
|
// things in the correct order with After() and Prepend(), the callback
|
||||||
|
// needs to be called on the reverse of the nodes.
|
||||||
|
if reverse {
|
||||||
|
for i, j := 0, len(ns)-1; i < j; i, j = i+1, j-1 {
|
||||||
|
ns[i], ns[j] = ns[j], ns[i]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for i, sn := range s.Nodes {
|
||||||
|
for _, n := range ns {
|
||||||
|
if i != lasti {
|
||||||
|
f(sn, cloneNode(n))
|
||||||
|
} else {
|
||||||
|
if n.Parent != nil {
|
||||||
|
n.Parent.RemoveChild(n)
|
||||||
|
}
|
||||||
|
f(sn, n)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return s
|
||||||
|
}
|
453
Godeps/_workspace/src/github.com/PuerkitoBio/goquery/manipulation_test.go
generated
vendored
Normal file
453
Godeps/_workspace/src/github.com/PuerkitoBio/goquery/manipulation_test.go
generated
vendored
Normal file
|
@ -0,0 +1,453 @@
|
||||||
|
package goquery
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
wrapHtml = "<div id=\"ins\">test string<div><p><em><b></b></em></p></div></div>"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestAfter(t *testing.T) {
|
||||||
|
doc := Doc2Clone()
|
||||||
|
doc.Find("#main").After("#nf6")
|
||||||
|
|
||||||
|
assertLength(t, doc.Find("#main #nf6").Nodes, 0)
|
||||||
|
assertLength(t, doc.Find("#foot #nf6").Nodes, 0)
|
||||||
|
assertLength(t, doc.Find("#main + #nf6").Nodes, 1)
|
||||||
|
printSel(t, doc.Selection)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestAfterMany(t *testing.T) {
|
||||||
|
doc := Doc2Clone()
|
||||||
|
doc.Find(".one").After("#nf6")
|
||||||
|
|
||||||
|
assertLength(t, doc.Find("#foot #nf6").Nodes, 1)
|
||||||
|
assertLength(t, doc.Find("#main #nf6").Nodes, 1)
|
||||||
|
assertLength(t, doc.Find(".one + #nf6").Nodes, 2)
|
||||||
|
printSel(t, doc.Selection)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestAfterWithRemoved(t *testing.T) {
|
||||||
|
doc := Doc2Clone()
|
||||||
|
s := doc.Find("#main").Remove()
|
||||||
|
s.After("#nf6")
|
||||||
|
|
||||||
|
assertLength(t, s.Find("#nf6").Nodes, 0)
|
||||||
|
assertLength(t, doc.Find("#nf6").Nodes, 0)
|
||||||
|
printSel(t, doc.Selection)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestAfterSelection(t *testing.T) {
|
||||||
|
doc := Doc2Clone()
|
||||||
|
doc.Find("#main").AfterSelection(doc.Find("#nf1, #nf2"))
|
||||||
|
|
||||||
|
assertLength(t, doc.Find("#main #nf1, #main #nf2").Nodes, 0)
|
||||||
|
assertLength(t, doc.Find("#foot #nf1, #foot #nf2").Nodes, 0)
|
||||||
|
assertLength(t, doc.Find("#main + #nf1, #nf1 + #nf2").Nodes, 2)
|
||||||
|
printSel(t, doc.Selection)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestAfterHtml(t *testing.T) {
|
||||||
|
doc := Doc2Clone()
|
||||||
|
doc.Find("#main").AfterHtml("<strong>new node</strong>")
|
||||||
|
|
||||||
|
assertLength(t, doc.Find("#main + strong").Nodes, 1)
|
||||||
|
printSel(t, doc.Selection)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestAppend(t *testing.T) {
|
||||||
|
doc := Doc2Clone()
|
||||||
|
doc.Find("#main").Append("#nf6")
|
||||||
|
|
||||||
|
assertLength(t, doc.Find("#foot #nf6").Nodes, 0)
|
||||||
|
assertLength(t, doc.Find("#main #nf6").Nodes, 1)
|
||||||
|
printSel(t, doc.Selection)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestAppendBody(t *testing.T) {
|
||||||
|
doc := Doc2Clone()
|
||||||
|
doc.Find("body").Append("#nf6")
|
||||||
|
|
||||||
|
assertLength(t, doc.Find("#foot #nf6").Nodes, 0)
|
||||||
|
assertLength(t, doc.Find("#main #nf6").Nodes, 0)
|
||||||
|
assertLength(t, doc.Find("body > #nf6").Nodes, 1)
|
||||||
|
printSel(t, doc.Selection)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestAppendSelection(t *testing.T) {
|
||||||
|
doc := Doc2Clone()
|
||||||
|
doc.Find("#main").AppendSelection(doc.Find("#nf1, #nf2"))
|
||||||
|
|
||||||
|
assertLength(t, doc.Find("#foot #nf1").Nodes, 0)
|
||||||
|
assertLength(t, doc.Find("#foot #nf2").Nodes, 0)
|
||||||
|
assertLength(t, doc.Find("#main #nf1").Nodes, 1)
|
||||||
|
assertLength(t, doc.Find("#main #nf2").Nodes, 1)
|
||||||
|
printSel(t, doc.Selection)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestAppendSelectionExisting(t *testing.T) {
|
||||||
|
doc := Doc2Clone()
|
||||||
|
doc.Find("#main").AppendSelection(doc.Find("#n1, #n2"))
|
||||||
|
|
||||||
|
assertClass(t, doc.Find("#main :nth-child(1)"), "three")
|
||||||
|
assertClass(t, doc.Find("#main :nth-child(5)"), "one")
|
||||||
|
assertClass(t, doc.Find("#main :nth-child(6)"), "two")
|
||||||
|
printSel(t, doc.Selection)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestAppendClone(t *testing.T) {
|
||||||
|
doc := Doc2Clone()
|
||||||
|
doc.Find("#n1").AppendSelection(doc.Find("#nf1").Clone())
|
||||||
|
|
||||||
|
assertLength(t, doc.Find("#foot #nf1").Nodes, 1)
|
||||||
|
assertLength(t, doc.Find("#main #nf1").Nodes, 1)
|
||||||
|
printSel(t, doc.Selection)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestAppendHtml(t *testing.T) {
|
||||||
|
doc := Doc2Clone()
|
||||||
|
doc.Find("div").AppendHtml("<strong>new node</strong>")
|
||||||
|
|
||||||
|
assertLength(t, doc.Find("strong").Nodes, 14)
|
||||||
|
printSel(t, doc.Selection)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestBefore(t *testing.T) {
|
||||||
|
doc := Doc2Clone()
|
||||||
|
doc.Find("#main").Before("#nf6")
|
||||||
|
|
||||||
|
assertLength(t, doc.Find("#main #nf6").Nodes, 0)
|
||||||
|
assertLength(t, doc.Find("#foot #nf6").Nodes, 0)
|
||||||
|
assertLength(t, doc.Find("body > #nf6:first-child").Nodes, 1)
|
||||||
|
printSel(t, doc.Selection)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestBeforeWithRemoved(t *testing.T) {
|
||||||
|
doc := Doc2Clone()
|
||||||
|
s := doc.Find("#main").Remove()
|
||||||
|
s.Before("#nf6")
|
||||||
|
|
||||||
|
assertLength(t, s.Find("#nf6").Nodes, 0)
|
||||||
|
assertLength(t, doc.Find("#nf6").Nodes, 0)
|
||||||
|
printSel(t, doc.Selection)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestBeforeSelection(t *testing.T) {
|
||||||
|
doc := Doc2Clone()
|
||||||
|
doc.Find("#main").BeforeSelection(doc.Find("#nf1, #nf2"))
|
||||||
|
|
||||||
|
assertLength(t, doc.Find("#main #nf1, #main #nf2").Nodes, 0)
|
||||||
|
assertLength(t, doc.Find("#foot #nf1, #foot #nf2").Nodes, 0)
|
||||||
|
assertLength(t, doc.Find("body > #nf1:first-child, #nf1 + #nf2").Nodes, 2)
|
||||||
|
printSel(t, doc.Selection)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestBeforeHtml(t *testing.T) {
|
||||||
|
doc := Doc2Clone()
|
||||||
|
doc.Find("#main").BeforeHtml("<strong>new node</strong>")
|
||||||
|
|
||||||
|
assertLength(t, doc.Find("body > strong:first-child").Nodes, 1)
|
||||||
|
printSel(t, doc.Selection)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestEmpty(t *testing.T) {
|
||||||
|
doc := Doc2Clone()
|
||||||
|
s := doc.Find("#main").Empty()
|
||||||
|
|
||||||
|
assertLength(t, doc.Find("#main").Children().Nodes, 0)
|
||||||
|
assertLength(t, s.Filter("div").Nodes, 6)
|
||||||
|
printSel(t, doc.Selection)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestPrepend(t *testing.T) {
|
||||||
|
doc := Doc2Clone()
|
||||||
|
doc.Find("#main").Prepend("#nf6")
|
||||||
|
|
||||||
|
assertLength(t, doc.Find("#foot #nf6").Nodes, 0)
|
||||||
|
assertLength(t, doc.Find("#main #nf6:first-child").Nodes, 1)
|
||||||
|
printSel(t, doc.Selection)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestPrependBody(t *testing.T) {
|
||||||
|
doc := Doc2Clone()
|
||||||
|
doc.Find("body").Prepend("#nf6")
|
||||||
|
|
||||||
|
assertLength(t, doc.Find("#foot #nf6").Nodes, 0)
|
||||||
|
assertLength(t, doc.Find("#main #nf6").Nodes, 0)
|
||||||
|
assertLength(t, doc.Find("body > #nf6:first-child").Nodes, 1)
|
||||||
|
printSel(t, doc.Selection)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestPrependSelection(t *testing.T) {
|
||||||
|
doc := Doc2Clone()
|
||||||
|
doc.Find("#main").PrependSelection(doc.Find("#nf1, #nf2"))
|
||||||
|
|
||||||
|
assertLength(t, doc.Find("#foot #nf1").Nodes, 0)
|
||||||
|
assertLength(t, doc.Find("#foot #nf2").Nodes, 0)
|
||||||
|
assertLength(t, doc.Find("#main #nf1:first-child").Nodes, 1)
|
||||||
|
assertLength(t, doc.Find("#main #nf2:nth-child(2)").Nodes, 1)
|
||||||
|
printSel(t, doc.Selection)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestPrependSelectionExisting(t *testing.T) {
|
||||||
|
doc := Doc2Clone()
|
||||||
|
doc.Find("#main").PrependSelection(doc.Find("#n5, #n6"))
|
||||||
|
|
||||||
|
assertClass(t, doc.Find("#main :nth-child(1)"), "five")
|
||||||
|
assertClass(t, doc.Find("#main :nth-child(2)"), "six")
|
||||||
|
assertClass(t, doc.Find("#main :nth-child(5)"), "three")
|
||||||
|
assertClass(t, doc.Find("#main :nth-child(6)"), "four")
|
||||||
|
printSel(t, doc.Selection)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestPrependClone(t *testing.T) {
|
||||||
|
doc := Doc2Clone()
|
||||||
|
doc.Find("#n1").PrependSelection(doc.Find("#nf1").Clone())
|
||||||
|
|
||||||
|
assertLength(t, doc.Find("#foot #nf1:first-child").Nodes, 1)
|
||||||
|
assertLength(t, doc.Find("#main #nf1:first-child").Nodes, 1)
|
||||||
|
printSel(t, doc.Selection)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestPrependHtml(t *testing.T) {
|
||||||
|
doc := Doc2Clone()
|
||||||
|
doc.Find("div").PrependHtml("<strong>new node</strong>")
|
||||||
|
|
||||||
|
assertLength(t, doc.Find("strong:first-child").Nodes, 14)
|
||||||
|
printSel(t, doc.Selection)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestRemove(t *testing.T) {
|
||||||
|
doc := Doc2Clone()
|
||||||
|
doc.Find("#nf1").Remove()
|
||||||
|
|
||||||
|
assertLength(t, doc.Find("#foot #nf1").Nodes, 0)
|
||||||
|
printSel(t, doc.Selection)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestRemoveAll(t *testing.T) {
|
||||||
|
doc := Doc2Clone()
|
||||||
|
doc.Find("*").Remove()
|
||||||
|
|
||||||
|
assertLength(t, doc.Find("*").Nodes, 0)
|
||||||
|
printSel(t, doc.Selection)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestRemoveRoot(t *testing.T) {
|
||||||
|
doc := Doc2Clone()
|
||||||
|
doc.Find("html").Remove()
|
||||||
|
|
||||||
|
assertLength(t, doc.Find("html").Nodes, 0)
|
||||||
|
printSel(t, doc.Selection)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestRemoveFiltered(t *testing.T) {
|
||||||
|
doc := Doc2Clone()
|
||||||
|
nf6 := doc.Find("#nf6")
|
||||||
|
s := doc.Find("div").RemoveFiltered("#nf6")
|
||||||
|
|
||||||
|
assertLength(t, doc.Find("#nf6").Nodes, 0)
|
||||||
|
assertLength(t, s.Nodes, 1)
|
||||||
|
if nf6.Nodes[0] != s.Nodes[0] {
|
||||||
|
t.Error("Removed node does not match original")
|
||||||
|
}
|
||||||
|
printSel(t, doc.Selection)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestReplaceWith(t *testing.T) {
|
||||||
|
doc := Doc2Clone()
|
||||||
|
|
||||||
|
doc.Find("#nf6").ReplaceWith("#main")
|
||||||
|
assertLength(t, doc.Find("#foot #main:last-child").Nodes, 1)
|
||||||
|
printSel(t, doc.Selection)
|
||||||
|
|
||||||
|
doc.Find("#foot").ReplaceWith("#main")
|
||||||
|
assertLength(t, doc.Find("#foot").Nodes, 0)
|
||||||
|
assertLength(t, doc.Find("#main").Nodes, 1)
|
||||||
|
|
||||||
|
printSel(t, doc.Selection)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestReplaceWithHtml(t *testing.T) {
|
||||||
|
doc := Doc2Clone()
|
||||||
|
doc.Find("#main, #foot").ReplaceWithHtml("<div id=\"replace\"></div>")
|
||||||
|
|
||||||
|
assertLength(t, doc.Find("#replace").Nodes, 2)
|
||||||
|
|
||||||
|
printSel(t, doc.Selection)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestReplaceWithSelection(t *testing.T) {
|
||||||
|
doc := Doc2Clone()
|
||||||
|
sel := doc.Find("#nf6").ReplaceWithSelection(doc.Find("#nf5"))
|
||||||
|
|
||||||
|
assertSelectionIs(t, sel, "#nf6")
|
||||||
|
assertLength(t, doc.Find("#nf6").Nodes, 0)
|
||||||
|
assertLength(t, doc.Find("#nf5").Nodes, 1)
|
||||||
|
|
||||||
|
printSel(t, doc.Selection)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestUnwrap(t *testing.T) {
|
||||||
|
doc := Doc2Clone()
|
||||||
|
|
||||||
|
doc.Find("#nf5").Unwrap()
|
||||||
|
assertLength(t, doc.Find("#foot").Nodes, 0)
|
||||||
|
assertLength(t, doc.Find("body > #nf1").Nodes, 1)
|
||||||
|
assertLength(t, doc.Find("body > #nf5").Nodes, 1)
|
||||||
|
|
||||||
|
printSel(t, doc.Selection)
|
||||||
|
|
||||||
|
doc = Doc2Clone()
|
||||||
|
|
||||||
|
doc.Find("#nf5, #n1").Unwrap()
|
||||||
|
assertLength(t, doc.Find("#foot").Nodes, 0)
|
||||||
|
assertLength(t, doc.Find("#main").Nodes, 0)
|
||||||
|
assertLength(t, doc.Find("body > #n1").Nodes, 1)
|
||||||
|
assertLength(t, doc.Find("body > #nf5").Nodes, 1)
|
||||||
|
|
||||||
|
printSel(t, doc.Selection)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestUnwrapBody(t *testing.T) {
|
||||||
|
doc := Doc2Clone()
|
||||||
|
|
||||||
|
doc.Find("#main").Unwrap()
|
||||||
|
assertLength(t, doc.Find("body").Nodes, 1)
|
||||||
|
assertLength(t, doc.Find("body > #main").Nodes, 1)
|
||||||
|
|
||||||
|
printSel(t, doc.Selection)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestUnwrapHead(t *testing.T) {
|
||||||
|
doc := Doc2Clone()
|
||||||
|
|
||||||
|
doc.Find("title").Unwrap()
|
||||||
|
assertLength(t, doc.Find("head").Nodes, 0)
|
||||||
|
assertLength(t, doc.Find("head > title").Nodes, 0)
|
||||||
|
assertLength(t, doc.Find("title").Nodes, 1)
|
||||||
|
|
||||||
|
printSel(t, doc.Selection)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestUnwrapHtml(t *testing.T) {
|
||||||
|
doc := Doc2Clone()
|
||||||
|
|
||||||
|
doc.Find("head").Unwrap()
|
||||||
|
assertLength(t, doc.Find("html").Nodes, 0)
|
||||||
|
assertLength(t, doc.Find("html head").Nodes, 0)
|
||||||
|
assertLength(t, doc.Find("head").Nodes, 1)
|
||||||
|
|
||||||
|
printSel(t, doc.Selection)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestWrap(t *testing.T) {
|
||||||
|
doc := Doc2Clone()
|
||||||
|
doc.Find("#nf1").Wrap("#nf2")
|
||||||
|
nf1 := doc.Find("#foot #nf2 #nf1")
|
||||||
|
assertLength(t, nf1.Nodes, 1)
|
||||||
|
|
||||||
|
nf2 := doc.Find("#nf2")
|
||||||
|
assertLength(t, nf2.Nodes, 2)
|
||||||
|
|
||||||
|
printSel(t, doc.Selection)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestWrapEmpty(t *testing.T) {
|
||||||
|
doc := Doc2Clone()
|
||||||
|
doc.Find("#nf1").Wrap("#doesnt-exist")
|
||||||
|
|
||||||
|
origHtml, _ := Doc2().Html()
|
||||||
|
newHtml, _ := doc.Html()
|
||||||
|
|
||||||
|
if origHtml != newHtml {
|
||||||
|
t.Error("Expected the two documents to be identical.")
|
||||||
|
}
|
||||||
|
|
||||||
|
printSel(t, doc.Selection)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestWrapHtml(t *testing.T) {
|
||||||
|
doc := Doc2Clone()
|
||||||
|
doc.Find(".odd").WrapHtml(wrapHtml)
|
||||||
|
nf2 := doc.Find("#ins #nf2")
|
||||||
|
assertLength(t, nf2.Nodes, 1)
|
||||||
|
printSel(t, doc.Selection)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestWrapSelection(t *testing.T) {
|
||||||
|
doc := Doc2Clone()
|
||||||
|
doc.Find("#nf1").WrapSelection(doc.Find("#nf2"))
|
||||||
|
nf1 := doc.Find("#foot #nf2 #nf1")
|
||||||
|
assertLength(t, nf1.Nodes, 1)
|
||||||
|
|
||||||
|
nf2 := doc.Find("#nf2")
|
||||||
|
assertLength(t, nf2.Nodes, 2)
|
||||||
|
|
||||||
|
printSel(t, doc.Selection)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestWrapAll(t *testing.T) {
|
||||||
|
doc := Doc2Clone()
|
||||||
|
doc.Find(".odd").WrapAll("#nf1")
|
||||||
|
nf1 := doc.Find("#main #nf1")
|
||||||
|
assertLength(t, nf1.Nodes, 1)
|
||||||
|
|
||||||
|
sel := nf1.Find("#n2 ~ #n4 ~ #n6 ~ #nf2 ~ #nf4 ~ #nf6")
|
||||||
|
assertLength(t, sel.Nodes, 1)
|
||||||
|
|
||||||
|
printSel(t, doc.Selection)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestWrapAllHtml(t *testing.T) {
|
||||||
|
doc := Doc2Clone()
|
||||||
|
doc.Find(".odd").WrapAllHtml(wrapHtml)
|
||||||
|
nf1 := doc.Find("#main div#ins div p em b #n2 ~ #n4 ~ #n6 ~ #nf2 ~ #nf4 ~ #nf6")
|
||||||
|
assertLength(t, nf1.Nodes, 1)
|
||||||
|
printSel(t, doc.Selection)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestWrapInnerNoContent(t *testing.T) {
|
||||||
|
doc := Doc2Clone()
|
||||||
|
doc.Find(".one").WrapInner(".two")
|
||||||
|
|
||||||
|
twos := doc.Find(".two")
|
||||||
|
assertLength(t, twos.Nodes, 4)
|
||||||
|
assertLength(t, doc.Find(".one .two").Nodes, 2)
|
||||||
|
|
||||||
|
printSel(t, doc.Selection)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestWrapInnerWithContent(t *testing.T) {
|
||||||
|
doc := Doc3Clone()
|
||||||
|
doc.Find(".one").WrapInner(".two")
|
||||||
|
|
||||||
|
twos := doc.Find(".two")
|
||||||
|
assertLength(t, twos.Nodes, 4)
|
||||||
|
assertLength(t, doc.Find(".one .two").Nodes, 2)
|
||||||
|
|
||||||
|
printSel(t, doc.Selection)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestWrapInnerNoWrapper(t *testing.T) {
|
||||||
|
doc := Doc2Clone()
|
||||||
|
doc.Find(".one").WrapInner(".not-exist")
|
||||||
|
|
||||||
|
twos := doc.Find(".two")
|
||||||
|
assertLength(t, twos.Nodes, 2)
|
||||||
|
assertLength(t, doc.Find(".one").Nodes, 2)
|
||||||
|
assertLength(t, doc.Find(".one .two").Nodes, 0)
|
||||||
|
|
||||||
|
printSel(t, doc.Selection)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestWrapInnerHtml(t *testing.T) {
|
||||||
|
doc := Doc2Clone()
|
||||||
|
doc.Find("#foot").WrapInnerHtml(wrapHtml)
|
||||||
|
|
||||||
|
foot := doc.Find("#foot div#ins div p em b #nf1 ~ #nf2 ~ #nf3")
|
||||||
|
assertLength(t, foot.Nodes, 1)
|
||||||
|
|
||||||
|
printSel(t, doc.Selection)
|
||||||
|
}
|
37
Godeps/_workspace/src/github.com/PuerkitoBio/goquery/misc/git/pre-commit
generated
vendored
Normal file
37
Godeps/_workspace/src/github.com/PuerkitoBio/goquery/misc/git/pre-commit
generated
vendored
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
#!/bin/sh
|
||||||
|
# Copyright 2012 The Go Authors. All rights reserved.
|
||||||
|
# Use of this source code is governed by a BSD-style
|
||||||
|
# license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
# git gofmt pre-commit hook
|
||||||
|
#
|
||||||
|
# To use, store as .git/hooks/pre-commit inside your repository and make sure
|
||||||
|
# it has execute permissions.
|
||||||
|
#
|
||||||
|
# This script does not handle file names that contain spaces.
|
||||||
|
|
||||||
|
# golint is purely informational, it doesn't fail with exit code != 0 if it finds something,
|
||||||
|
# because it may find a lot of false positives. Just print out its result for information.
|
||||||
|
echo "lint result (informational only):"
|
||||||
|
golint .
|
||||||
|
|
||||||
|
# go vet returns 1 if an error was found. Exit the hook with this exit code.
|
||||||
|
go vet ./...
|
||||||
|
vetres=$?
|
||||||
|
|
||||||
|
# Check for gofmt problems and report if any.
|
||||||
|
gofiles=$(git diff --cached --name-only --diff-filter=ACM | grep '.go$')
|
||||||
|
[ -z "$gofiles" ] && echo "EXIT $vetres" && exit $vetres
|
||||||
|
|
||||||
|
unformatted=$(gofmt -l $gofiles)
|
||||||
|
[ -z "$unformatted" ] && echo "EXIT $vetres" && exit $vetres
|
||||||
|
|
||||||
|
# Some files are not gofmt'd. Print message and fail.
|
||||||
|
|
||||||
|
echo >&2 "Go files must be formatted with gofmt. Please run:"
|
||||||
|
for fn in $unformatted; do
|
||||||
|
echo >&2 " gofmt -w $PWD/$fn"
|
||||||
|
done
|
||||||
|
|
||||||
|
echo "EXIT 1"
|
||||||
|
exit 1
|
278
Godeps/_workspace/src/github.com/PuerkitoBio/goquery/property.go
generated
vendored
Normal file
278
Godeps/_workspace/src/github.com/PuerkitoBio/goquery/property.go
generated
vendored
Normal file
|
@ -0,0 +1,278 @@
|
||||||
|
package goquery
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"regexp"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"golang.org/x/net/html"
|
||||||
|
)
|
||||||
|
|
||||||
|
var rxClassTrim = regexp.MustCompile("[\t\r\n]")
|
||||||
|
|
||||||
|
// Attr gets the specified attribute's value for the first element in the
|
||||||
|
// Selection. To get the value for each element individually, use a looping
|
||||||
|
// construct such as Each or Map method.
|
||||||
|
func (s *Selection) Attr(attrName string) (val string, exists bool) {
|
||||||
|
if len(s.Nodes) == 0 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
return getAttributeValue(attrName, s.Nodes[0])
|
||||||
|
}
|
||||||
|
|
||||||
|
// AttrOr works like Attr but returns default value if attribute is not present.
|
||||||
|
func (s *Selection) AttrOr(attrName, defaultValue string) string {
|
||||||
|
if len(s.Nodes) == 0 {
|
||||||
|
return defaultValue
|
||||||
|
}
|
||||||
|
|
||||||
|
val, exists := getAttributeValue(attrName, s.Nodes[0])
|
||||||
|
if !exists {
|
||||||
|
return defaultValue
|
||||||
|
}
|
||||||
|
|
||||||
|
return val
|
||||||
|
}
|
||||||
|
|
||||||
|
// RemoveAttr removes the named attribute from each element in the set of matched elements.
|
||||||
|
func (s *Selection) RemoveAttr(attrName string) *Selection {
|
||||||
|
for _, n := range s.Nodes {
|
||||||
|
removeAttr(n, attrName)
|
||||||
|
}
|
||||||
|
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetAttr sets the given attribute on each element in the set of matched elements.
|
||||||
|
func (s *Selection) SetAttr(attrName, val string) *Selection {
|
||||||
|
for _, n := range s.Nodes {
|
||||||
|
attr := getAttributePtr(attrName, n)
|
||||||
|
if attr == nil {
|
||||||
|
n.Attr = append(n.Attr, html.Attribute{Key: attrName, Val: val})
|
||||||
|
} else {
|
||||||
|
attr.Val = val
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
|
||||||
|
// Text gets the combined text contents of each element in the set of matched
|
||||||
|
// elements, including their descendants.
|
||||||
|
func (s *Selection) Text() string {
|
||||||
|
var buf bytes.Buffer
|
||||||
|
|
||||||
|
// Slightly optimized vs calling Each: no single selection object created
|
||||||
|
for _, n := range s.Nodes {
|
||||||
|
buf.WriteString(getNodeText(n))
|
||||||
|
}
|
||||||
|
return buf.String()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Size is an alias for Length.
|
||||||
|
func (s *Selection) Size() int {
|
||||||
|
return s.Length()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Length returns the number of elements in the Selection object.
|
||||||
|
func (s *Selection) Length() int {
|
||||||
|
return len(s.Nodes)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Html gets the HTML contents of the first element in the set of matched
|
||||||
|
// elements. It includes text and comment nodes.
|
||||||
|
func (s *Selection) Html() (ret string, e error) {
|
||||||
|
// Since there is no .innerHtml, the HTML content must be re-created from
|
||||||
|
// the nodes using html.Render.
|
||||||
|
var buf bytes.Buffer
|
||||||
|
|
||||||
|
if len(s.Nodes) > 0 {
|
||||||
|
for c := s.Nodes[0].FirstChild; c != nil; c = c.NextSibling {
|
||||||
|
e = html.Render(&buf, c)
|
||||||
|
if e != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ret = buf.String()
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddClass adds the given class(es) to each element in the set of matched elements.
|
||||||
|
// Multiple class names can be specified, separated by a space or via multiple arguments.
|
||||||
|
func (s *Selection) AddClass(class ...string) *Selection {
|
||||||
|
classStr := strings.TrimSpace(strings.Join(class, " "))
|
||||||
|
|
||||||
|
if classStr == "" {
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
|
||||||
|
tcls := getClassesSlice(classStr)
|
||||||
|
for _, n := range s.Nodes {
|
||||||
|
curClasses, attr := getClassesAndAttr(n, true)
|
||||||
|
for _, newClass := range tcls {
|
||||||
|
if strings.Index(curClasses, " "+newClass+" ") == -1 {
|
||||||
|
curClasses += newClass + " "
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
setClasses(n, attr, curClasses)
|
||||||
|
}
|
||||||
|
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
|
||||||
|
// HasClass determines whether any of the matched elements are assigned the
|
||||||
|
// given class.
|
||||||
|
func (s *Selection) HasClass(class string) bool {
|
||||||
|
class = " " + class + " "
|
||||||
|
for _, n := range s.Nodes {
|
||||||
|
classes, _ := getClassesAndAttr(n, false)
|
||||||
|
if strings.Index(classes, class) > -1 {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// RemoveClass removes the given class(es) from each element in the set of matched elements.
|
||||||
|
// Multiple class names can be specified, separated by a space or via multiple arguments.
|
||||||
|
// If no class name is provided, all classes are removed.
|
||||||
|
func (s *Selection) RemoveClass(class ...string) *Selection {
|
||||||
|
var rclasses []string
|
||||||
|
|
||||||
|
classStr := strings.TrimSpace(strings.Join(class, " "))
|
||||||
|
remove := classStr == ""
|
||||||
|
|
||||||
|
if !remove {
|
||||||
|
rclasses = getClassesSlice(classStr)
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, n := range s.Nodes {
|
||||||
|
if remove {
|
||||||
|
removeAttr(n, "class")
|
||||||
|
} else {
|
||||||
|
classes, attr := getClassesAndAttr(n, true)
|
||||||
|
for _, rcl := range rclasses {
|
||||||
|
classes = strings.Replace(classes, " "+rcl+" ", " ", -1)
|
||||||
|
}
|
||||||
|
|
||||||
|
setClasses(n, attr, classes)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
|
||||||
|
// ToggleClass adds or removes the given class(es) for each element in the set of matched elements.
|
||||||
|
// Multiple class names can be specified, separated by a space or via multiple arguments.
|
||||||
|
func (s *Selection) ToggleClass(class ...string) *Selection {
|
||||||
|
classStr := strings.TrimSpace(strings.Join(class, " "))
|
||||||
|
|
||||||
|
if classStr == "" {
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
|
||||||
|
tcls := getClassesSlice(classStr)
|
||||||
|
|
||||||
|
for _, n := range s.Nodes {
|
||||||
|
classes, attr := getClassesAndAttr(n, true)
|
||||||
|
for _, tcl := range tcls {
|
||||||
|
if strings.Index(classes, " "+tcl+" ") != -1 {
|
||||||
|
classes = strings.Replace(classes, " "+tcl+" ", " ", -1)
|
||||||
|
} else {
|
||||||
|
classes += tcl + " "
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
setClasses(n, attr, classes)
|
||||||
|
}
|
||||||
|
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the specified node's text content.
|
||||||
|
func getNodeText(node *html.Node) string {
|
||||||
|
if node.Type == html.TextNode {
|
||||||
|
// Keep newlines and spaces, like jQuery
|
||||||
|
return node.Data
|
||||||
|
} else if node.FirstChild != nil {
|
||||||
|
var buf bytes.Buffer
|
||||||
|
for c := node.FirstChild; c != nil; c = c.NextSibling {
|
||||||
|
buf.WriteString(getNodeText(c))
|
||||||
|
}
|
||||||
|
return buf.String()
|
||||||
|
}
|
||||||
|
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func getAttributePtr(attrName string, n *html.Node) *html.Attribute {
|
||||||
|
if n == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
for i, a := range n.Attr {
|
||||||
|
if a.Key == attrName {
|
||||||
|
return &n.Attr[i]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Private function to get the specified attribute's value from a node.
|
||||||
|
func getAttributeValue(attrName string, n *html.Node) (val string, exists bool) {
|
||||||
|
if a := getAttributePtr(attrName, n); a != nil {
|
||||||
|
val = a.Val
|
||||||
|
exists = true
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get and normalize the "class" attribute from the node.
|
||||||
|
func getClassesAndAttr(n *html.Node, create bool) (classes string, attr *html.Attribute) {
|
||||||
|
// Applies only to element nodes
|
||||||
|
if n.Type == html.ElementNode {
|
||||||
|
attr = getAttributePtr("class", n)
|
||||||
|
if attr == nil && create {
|
||||||
|
n.Attr = append(n.Attr, html.Attribute{
|
||||||
|
Key: "class",
|
||||||
|
Val: "",
|
||||||
|
})
|
||||||
|
attr = &n.Attr[len(n.Attr)-1]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if attr == nil {
|
||||||
|
classes = " "
|
||||||
|
} else {
|
||||||
|
classes = rxClassTrim.ReplaceAllString(" "+attr.Val+" ", " ")
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func getClassesSlice(classes string) []string {
|
||||||
|
return strings.Split(rxClassTrim.ReplaceAllString(" "+classes+" ", " "), " ")
|
||||||
|
}
|
||||||
|
|
||||||
|
func removeAttr(n *html.Node, attrName string) {
|
||||||
|
for i, a := range n.Attr {
|
||||||
|
if a.Key == attrName {
|
||||||
|
n.Attr[i], n.Attr[len(n.Attr)-1], n.Attr =
|
||||||
|
n.Attr[len(n.Attr)-1], html.Attribute{}, n.Attr[:len(n.Attr)-1]
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func setClasses(n *html.Node, attr *html.Attribute, classes string) {
|
||||||
|
classes = strings.TrimSpace(classes)
|
||||||
|
if classes == "" {
|
||||||
|
removeAttr(n, "class")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
attr.Val = classes
|
||||||
|
}
|
252
Godeps/_workspace/src/github.com/PuerkitoBio/goquery/property_test.go
generated
vendored
Normal file
252
Godeps/_workspace/src/github.com/PuerkitoBio/goquery/property_test.go
generated
vendored
Normal file
|
@ -0,0 +1,252 @@
|
||||||
|
package goquery
|
||||||
|
|
||||||
|
import (
|
||||||
|
"regexp"
|
||||||
|
"strings"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestAttrExists(t *testing.T) {
|
||||||
|
if val, ok := Doc().Find("a").Attr("href"); !ok {
|
||||||
|
t.Error("Expected a value for the href attribute.")
|
||||||
|
} else {
|
||||||
|
t.Logf("Href of first anchor: %v.", val)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestAttrOr(t *testing.T) {
|
||||||
|
if val := Doc().Find("a").AttrOr("fake-attribute", "alternative"); val != "alternative" {
|
||||||
|
t.Error("Expected an alternative value for 'fake-attribute' attribute.")
|
||||||
|
} else {
|
||||||
|
t.Logf("Value returned for not existing attribute: %v.", val)
|
||||||
|
}
|
||||||
|
if val := Doc().Find("zz").AttrOr("fake-attribute", "alternative"); val != "alternative" {
|
||||||
|
t.Error("Expected an alternative value for 'fake-attribute' on an empty selection.")
|
||||||
|
} else {
|
||||||
|
t.Logf("Value returned for empty selection: %v.", val)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestAttrNotExist(t *testing.T) {
|
||||||
|
if val, ok := Doc().Find("div.row-fluid").Attr("href"); ok {
|
||||||
|
t.Errorf("Expected no value for the href attribute, got %v.", val)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestRemoveAttr(t *testing.T) {
|
||||||
|
sel := Doc2Clone().Find("div")
|
||||||
|
|
||||||
|
sel.RemoveAttr("id")
|
||||||
|
|
||||||
|
_, ok := sel.Attr("id")
|
||||||
|
if ok {
|
||||||
|
t.Error("Expected there to be no id attributes set")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSetAttr(t *testing.T) {
|
||||||
|
sel := Doc2Clone().Find("#main")
|
||||||
|
|
||||||
|
sel.SetAttr("id", "not-main")
|
||||||
|
|
||||||
|
val, ok := sel.Attr("id")
|
||||||
|
if !ok {
|
||||||
|
t.Error("Expected an id attribute on main")
|
||||||
|
}
|
||||||
|
|
||||||
|
if val != "not-main" {
|
||||||
|
t.Errorf("Expected an attribute id to be not-main, got %s", val)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSetAttr2(t *testing.T) {
|
||||||
|
sel := Doc2Clone().Find("#main")
|
||||||
|
|
||||||
|
sel.SetAttr("foo", "bar")
|
||||||
|
|
||||||
|
val, ok := sel.Attr("foo")
|
||||||
|
if !ok {
|
||||||
|
t.Error("Expected an 'foo' attribute on main")
|
||||||
|
}
|
||||||
|
|
||||||
|
if val != "bar" {
|
||||||
|
t.Errorf("Expected an attribute 'foo' to be 'bar', got '%s'", val)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestText(t *testing.T) {
|
||||||
|
txt := Doc().Find("h1").Text()
|
||||||
|
if strings.Trim(txt, " \n\r\t") != "Provok.in" {
|
||||||
|
t.Errorf("Expected text to be Provok.in, found %s.", txt)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestText2(t *testing.T) {
|
||||||
|
txt := Doc().Find(".hero-unit .container-fluid .row-fluid:nth-child(1)").Text()
|
||||||
|
if ok, e := regexp.MatchString(`^\s+Provok\.in\s+Prove your point.\s+$`, txt); !ok || e != nil {
|
||||||
|
t.Errorf("Expected text to be Provok.in Prove your point., found %s.", txt)
|
||||||
|
if e != nil {
|
||||||
|
t.Logf("Error: %s.", e.Error())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestText3(t *testing.T) {
|
||||||
|
txt := Doc().Find(".pvk-gutter").First().Text()
|
||||||
|
// There's an character in there...
|
||||||
|
if ok, e := regexp.MatchString(`^[\s\x{00A0}]+$`, txt); !ok || e != nil {
|
||||||
|
t.Errorf("Expected spaces, found <%v>.", txt)
|
||||||
|
if e != nil {
|
||||||
|
t.Logf("Error: %s.", e.Error())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestHtml(t *testing.T) {
|
||||||
|
txt, e := Doc().Find("h1").Html()
|
||||||
|
if e != nil {
|
||||||
|
t.Errorf("Error: %s.", e)
|
||||||
|
}
|
||||||
|
|
||||||
|
if ok, e := regexp.MatchString(`^\s*<a href="/">Provok<span class="green">\.</span><span class="red">i</span>n</a>\s*$`, txt); !ok || e != nil {
|
||||||
|
t.Errorf("Unexpected HTML content, found %s.", txt)
|
||||||
|
if e != nil {
|
||||||
|
t.Logf("Error: %s.", e.Error())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestNbsp(t *testing.T) {
|
||||||
|
src := `<p>Some text</p>`
|
||||||
|
d, err := NewDocumentFromReader(strings.NewReader(src))
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
txt := d.Find("p").Text()
|
||||||
|
ix := strings.Index(txt, "\u00a0")
|
||||||
|
if ix != 4 {
|
||||||
|
t.Errorf("Text: expected a non-breaking space at index 4, got %d", ix)
|
||||||
|
}
|
||||||
|
|
||||||
|
h, err := d.Find("p").Html()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
ix = strings.Index(h, "\u00a0")
|
||||||
|
if ix != 4 {
|
||||||
|
t.Errorf("Html: expected a non-breaking space at index 4, got %d", ix)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestAddClass(t *testing.T) {
|
||||||
|
sel := Doc2Clone().Find("#main")
|
||||||
|
sel.AddClass("main main main")
|
||||||
|
|
||||||
|
// Make sure that class was only added once
|
||||||
|
if a, ok := sel.Attr("class"); !ok || a != "main" {
|
||||||
|
t.Error("Expected #main to have class main")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestAddClassSimilar(t *testing.T) {
|
||||||
|
sel := Doc2Clone().Find("#nf5")
|
||||||
|
sel.AddClass("odd")
|
||||||
|
|
||||||
|
assertClass(t, sel, "odd")
|
||||||
|
assertClass(t, sel, "odder")
|
||||||
|
printSel(t, sel.Parent())
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestAddEmptyClass(t *testing.T) {
|
||||||
|
sel := Doc2Clone().Find("#main")
|
||||||
|
sel.AddClass("")
|
||||||
|
|
||||||
|
// Make sure that class was only added once
|
||||||
|
if a, ok := sel.Attr("class"); ok {
|
||||||
|
t.Errorf("Expected #main to not to have a class, have: %s", a)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestAddClasses(t *testing.T) {
|
||||||
|
sel := Doc2Clone().Find("#main")
|
||||||
|
sel.AddClass("a b")
|
||||||
|
|
||||||
|
// Make sure that class was only added once
|
||||||
|
if !sel.HasClass("a") || !sel.HasClass("b") {
|
||||||
|
t.Errorf("#main does not have classes")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestHasClass(t *testing.T) {
|
||||||
|
sel := Doc().Find("div")
|
||||||
|
if !sel.HasClass("span12") {
|
||||||
|
t.Error("Expected at least one div to have class span12.")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestHasClassNone(t *testing.T) {
|
||||||
|
sel := Doc().Find("h2")
|
||||||
|
if sel.HasClass("toto") {
|
||||||
|
t.Error("Expected h1 to have no class.")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestHasClassNotFirst(t *testing.T) {
|
||||||
|
sel := Doc().Find(".alert")
|
||||||
|
if !sel.HasClass("alert-error") {
|
||||||
|
t.Error("Expected .alert to also have class .alert-error.")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestRemoveClass(t *testing.T) {
|
||||||
|
sel := Doc2Clone().Find("#nf1")
|
||||||
|
sel.RemoveClass("one row")
|
||||||
|
|
||||||
|
if !sel.HasClass("even") || sel.HasClass("one") || sel.HasClass("row") {
|
||||||
|
classes, _ := sel.Attr("class")
|
||||||
|
t.Error("Expected #nf1 to have class even, has ", classes)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestRemoveClassSimilar(t *testing.T) {
|
||||||
|
sel := Doc2Clone().Find("#nf5, #nf6")
|
||||||
|
assertLength(t, sel.Nodes, 2)
|
||||||
|
|
||||||
|
sel.RemoveClass("odd")
|
||||||
|
assertClass(t, sel.Eq(0), "odder")
|
||||||
|
printSel(t, sel)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestRemoveAllClasses(t *testing.T) {
|
||||||
|
sel := Doc2Clone().Find("#nf1")
|
||||||
|
sel.RemoveClass()
|
||||||
|
|
||||||
|
if a, ok := sel.Attr("class"); ok {
|
||||||
|
t.Error("All classes were not removed, has ", a)
|
||||||
|
}
|
||||||
|
|
||||||
|
sel = Doc2Clone().Find("#main")
|
||||||
|
sel.RemoveClass()
|
||||||
|
if a, ok := sel.Attr("class"); ok {
|
||||||
|
t.Error("All classes were not removed, has ", a)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestToggleClass(t *testing.T) {
|
||||||
|
sel := Doc2Clone().Find("#nf1")
|
||||||
|
|
||||||
|
sel.ToggleClass("one")
|
||||||
|
if sel.HasClass("one") {
|
||||||
|
t.Error("Expected #nf1 to not have class one")
|
||||||
|
}
|
||||||
|
|
||||||
|
sel.ToggleClass("one")
|
||||||
|
if !sel.HasClass("one") {
|
||||||
|
t.Error("Expected #nf1 to have class one")
|
||||||
|
}
|
||||||
|
|
||||||
|
sel.ToggleClass("one even row")
|
||||||
|
if a, ok := sel.Attr("class"); ok {
|
||||||
|
t.Errorf("Expected #nf1 to have no classes, have %q", a)
|
||||||
|
}
|
||||||
|
}
|
56
Godeps/_workspace/src/github.com/PuerkitoBio/goquery/query.go
generated
vendored
Normal file
56
Godeps/_workspace/src/github.com/PuerkitoBio/goquery/query.go
generated
vendored
Normal file
|
@ -0,0 +1,56 @@
|
||||||
|
package goquery
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/andybalholm/cascadia"
|
||||||
|
"golang.org/x/net/html"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Is checks the current matched set of elements against a selector and
|
||||||
|
// returns true if at least one of these elements matches.
|
||||||
|
func (s *Selection) Is(selector string) bool {
|
||||||
|
if len(s.Nodes) > 0 {
|
||||||
|
return s.IsMatcher(cascadia.MustCompile(selector))
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsMatcher checks the current matched set of elements against a matcher and
|
||||||
|
// returns true if at least one of these elements matches.
|
||||||
|
func (s *Selection) IsMatcher(m Matcher) bool {
|
||||||
|
if len(s.Nodes) > 0 {
|
||||||
|
if len(s.Nodes) == 1 {
|
||||||
|
return m.Match(s.Nodes[0])
|
||||||
|
}
|
||||||
|
return len(m.Filter(s.Nodes)) > 0
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsFunction checks the current matched set of elements against a predicate and
|
||||||
|
// returns true if at least one of these elements matches.
|
||||||
|
func (s *Selection) IsFunction(f func(int, *Selection) bool) bool {
|
||||||
|
return s.FilterFunction(f).Length() > 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsSelection checks the current matched set of elements against a Selection object
|
||||||
|
// and returns true if at least one of these elements matches.
|
||||||
|
func (s *Selection) IsSelection(sel *Selection) bool {
|
||||||
|
return s.FilterSelection(sel).Length() > 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsNodes checks the current matched set of elements against the specified nodes
|
||||||
|
// and returns true if at least one of these elements matches.
|
||||||
|
func (s *Selection) IsNodes(nodes ...*html.Node) bool {
|
||||||
|
return s.FilterNodes(nodes...).Length() > 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// Contains returns true if the specified Node is within,
|
||||||
|
// at any depth, one of the nodes in the Selection object.
|
||||||
|
// It is NOT inclusive, to behave like jQuery's implementation, and
|
||||||
|
// unlike Javascript's .contains, so if the contained
|
||||||
|
// node is itself in the selection, it returns false.
|
||||||
|
func (s *Selection) Contains(n *html.Node) bool {
|
||||||
|
return sliceContains(s.Nodes, n)
|
||||||
|
}
|
96
Godeps/_workspace/src/github.com/PuerkitoBio/goquery/query_test.go
generated
vendored
Normal file
96
Godeps/_workspace/src/github.com/PuerkitoBio/goquery/query_test.go
generated
vendored
Normal file
|
@ -0,0 +1,96 @@
|
||||||
|
package goquery
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestIs(t *testing.T) {
|
||||||
|
sel := Doc().Find(".footer p:nth-child(1)")
|
||||||
|
if !sel.Is("p") {
|
||||||
|
t.Error("Expected .footer p:nth-child(1) to be p.")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestIsPositional(t *testing.T) {
|
||||||
|
sel := Doc().Find(".footer p:nth-child(2)")
|
||||||
|
if !sel.Is("p:nth-child(2)") {
|
||||||
|
t.Error("Expected .footer p:nth-child(2) to be p:nth-child(2).")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestIsPositionalNot(t *testing.T) {
|
||||||
|
sel := Doc().Find(".footer p:nth-child(1)")
|
||||||
|
if sel.Is("p:nth-child(2)") {
|
||||||
|
t.Error("Expected .footer p:nth-child(1) NOT to be p:nth-child(2).")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestIsFunction(t *testing.T) {
|
||||||
|
ok := Doc().Find("div").IsFunction(func(i int, s *Selection) bool {
|
||||||
|
return s.HasClass("container-fluid")
|
||||||
|
})
|
||||||
|
|
||||||
|
if !ok {
|
||||||
|
t.Error("Expected some div to have a container-fluid class.")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestIsFunctionRollback(t *testing.T) {
|
||||||
|
ok := Doc().Find("div").IsFunction(func(i int, s *Selection) bool {
|
||||||
|
return s.HasClass("container-fluid")
|
||||||
|
})
|
||||||
|
|
||||||
|
if !ok {
|
||||||
|
t.Error("Expected some div to have a container-fluid class.")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestIsSelection(t *testing.T) {
|
||||||
|
sel := Doc().Find("div")
|
||||||
|
sel2 := Doc().Find(".pvk-gutter")
|
||||||
|
|
||||||
|
if !sel.IsSelection(sel2) {
|
||||||
|
t.Error("Expected some div to have a pvk-gutter class.")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestIsSelectionNot(t *testing.T) {
|
||||||
|
sel := Doc().Find("div")
|
||||||
|
sel2 := Doc().Find("a")
|
||||||
|
|
||||||
|
if sel.IsSelection(sel2) {
|
||||||
|
t.Error("Expected some div NOT to be an anchor.")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestIsNodes(t *testing.T) {
|
||||||
|
sel := Doc().Find("div")
|
||||||
|
sel2 := Doc().Find(".footer")
|
||||||
|
|
||||||
|
if !sel.IsNodes(sel2.Nodes[0]) {
|
||||||
|
t.Error("Expected some div to have a footer class.")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestDocContains(t *testing.T) {
|
||||||
|
sel := Doc().Find("h1")
|
||||||
|
if !Doc().Contains(sel.Nodes[0]) {
|
||||||
|
t.Error("Expected document to contain H1 tag.")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSelContains(t *testing.T) {
|
||||||
|
sel := Doc().Find(".row-fluid")
|
||||||
|
sel2 := Doc().Find("a[ng-click]")
|
||||||
|
if !sel.Contains(sel2.Nodes[0]) {
|
||||||
|
t.Error("Expected .row-fluid to contain a[ng-click] tag.")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSelNotContains(t *testing.T) {
|
||||||
|
sel := Doc().Find("a.link")
|
||||||
|
sel2 := Doc().Find("span")
|
||||||
|
if sel.Contains(sel2.Nodes[0]) {
|
||||||
|
t.Error("Expected a.link to NOT contain span tag.")
|
||||||
|
}
|
||||||
|
}
|
855
Godeps/_workspace/src/github.com/PuerkitoBio/goquery/testdata/gotesting.html
generated
vendored
Normal file
855
Godeps/_workspace/src/github.com/PuerkitoBio/goquery/testdata/gotesting.html
generated
vendored
Normal file
|
@ -0,0 +1,855 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
|
||||||
|
|
||||||
|
<title>testing - The Go Programming Language</title>
|
||||||
|
|
||||||
|
<link type="text/css" rel="stylesheet" href="/doc/style.css">
|
||||||
|
<script type="text/javascript" src="/doc/godocs.js"></script>
|
||||||
|
|
||||||
|
<link rel="search" type="application/opensearchdescription+xml" title="godoc" href="/opensearch.xml" />
|
||||||
|
|
||||||
|
<script type="text/javascript">
|
||||||
|
var _gaq = _gaq || [];
|
||||||
|
_gaq.push(["_setAccount", "UA-11222381-2"]);
|
||||||
|
_gaq.push(["_trackPageview"]);
|
||||||
|
</script>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
|
||||||
|
<div id="topbar"><div class="container wide">
|
||||||
|
|
||||||
|
<form method="GET" action="/search">
|
||||||
|
<div id="menu">
|
||||||
|
<a href="/doc/">Documents</a>
|
||||||
|
<a href="/ref/">References</a>
|
||||||
|
<a href="/pkg/">Packages</a>
|
||||||
|
<a href="/project/">The Project</a>
|
||||||
|
<a href="/help/">Help</a>
|
||||||
|
<input type="text" id="search" name="q" class="inactive" value="Search">
|
||||||
|
</div>
|
||||||
|
<div id="heading"><a href="/">The Go Programming Language</a></div>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
</div></div>
|
||||||
|
|
||||||
|
<div id="page" class="wide">
|
||||||
|
|
||||||
|
|
||||||
|
<div id="plusone"><g:plusone size="small" annotation="none"></g:plusone></div>
|
||||||
|
<h1>Package testing</h1>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<div id="nav"></div>
|
||||||
|
|
||||||
|
|
||||||
|
<!--
|
||||||
|
Copyright 2009 The Go Authors. All rights reserved.
|
||||||
|
Use of this source code is governed by a BSD-style
|
||||||
|
license that can be found in the LICENSE file.
|
||||||
|
-->
|
||||||
|
|
||||||
|
|
||||||
|
<div id="short-nav">
|
||||||
|
<dl>
|
||||||
|
<dd><code>import "testing"</code></dd>
|
||||||
|
</dl>
|
||||||
|
<dl>
|
||||||
|
<dd><a href="#overview" class="overviewLink">Overview</a></dd>
|
||||||
|
<dd><a href="#index">Index</a></dd>
|
||||||
|
|
||||||
|
|
||||||
|
<dd><a href="#subdirectories">Subdirectories</a></dd>
|
||||||
|
|
||||||
|
</dl>
|
||||||
|
</div>
|
||||||
|
<!-- The package's Name is printed as title by the top-level template -->
|
||||||
|
<div id="overview" class="toggleVisible">
|
||||||
|
<div class="collapsed">
|
||||||
|
<h2 class="toggleButton" title="Click to show Overview section">Overview ▹</h2>
|
||||||
|
</div>
|
||||||
|
<div class="expanded">
|
||||||
|
<h2 class="toggleButton" title="Click to hide Overview section">Overview ▾</h2>
|
||||||
|
<p>
|
||||||
|
Package testing provides support for automated testing of Go packages.
|
||||||
|
It is intended to be used in concert with the “go test” command, which automates
|
||||||
|
execution of any function of the form
|
||||||
|
</p>
|
||||||
|
<pre>func TestXxx(*testing.T)
|
||||||
|
</pre>
|
||||||
|
<p>
|
||||||
|
where Xxx can be any alphanumeric string (but the first letter must not be in
|
||||||
|
[a-z]) and serves to identify the test routine.
|
||||||
|
These TestXxx routines should be declared within the package they are testing.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Functions of the form
|
||||||
|
</p>
|
||||||
|
<pre>func BenchmarkXxx(*testing.B)
|
||||||
|
</pre>
|
||||||
|
<p>
|
||||||
|
are considered benchmarks, and are executed by the "go test" command when
|
||||||
|
the -test.bench flag is provided.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
A sample benchmark function looks like this:
|
||||||
|
</p>
|
||||||
|
<pre>func BenchmarkHello(b *testing.B) {
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
fmt.Sprintf("hello")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</pre>
|
||||||
|
<p>
|
||||||
|
The benchmark package will vary b.N until the benchmark function lasts
|
||||||
|
long enough to be timed reliably. The output
|
||||||
|
</p>
|
||||||
|
<pre>testing.BenchmarkHello 10000000 282 ns/op
|
||||||
|
</pre>
|
||||||
|
<p>
|
||||||
|
means that the loop ran 10000000 times at a speed of 282 ns per loop.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
If a benchmark needs some expensive setup before running, the timer
|
||||||
|
may be stopped:
|
||||||
|
</p>
|
||||||
|
<pre>func BenchmarkBigLen(b *testing.B) {
|
||||||
|
b.StopTimer()
|
||||||
|
big := NewBig()
|
||||||
|
b.StartTimer()
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
big.Len()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</pre>
|
||||||
|
<p>
|
||||||
|
The package also runs and verifies example code. Example functions may
|
||||||
|
include a concluding comment that begins with "Output:" and is compared with
|
||||||
|
the standard output of the function when the tests are run, as in these
|
||||||
|
examples of an example:
|
||||||
|
</p>
|
||||||
|
<pre>func ExampleHello() {
|
||||||
|
fmt.Println("hello")
|
||||||
|
// Output: hello
|
||||||
|
}
|
||||||
|
|
||||||
|
func ExampleSalutations() {
|
||||||
|
fmt.Println("hello, and")
|
||||||
|
fmt.Println("goodbye")
|
||||||
|
// Output:
|
||||||
|
// hello, and
|
||||||
|
// goodbye
|
||||||
|
}
|
||||||
|
</pre>
|
||||||
|
<p>
|
||||||
|
Example functions without output comments are compiled but not executed.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
The naming convention to declare examples for a function F, a type T and
|
||||||
|
method M on type T are:
|
||||||
|
</p>
|
||||||
|
<pre>func ExampleF() { ... }
|
||||||
|
func ExampleT() { ... }
|
||||||
|
func ExampleT_M() { ... }
|
||||||
|
</pre>
|
||||||
|
<p>
|
||||||
|
Multiple example functions for a type/function/method may be provided by
|
||||||
|
appending a distinct suffix to the name. The suffix must start with a
|
||||||
|
lower-case letter.
|
||||||
|
</p>
|
||||||
|
<pre>func ExampleF_suffix() { ... }
|
||||||
|
func ExampleT_suffix() { ... }
|
||||||
|
func ExampleT_M_suffix() { ... }
|
||||||
|
</pre>
|
||||||
|
<p>
|
||||||
|
The entire test file is presented as the example when it contains a single
|
||||||
|
example function, at least one other function, type, variable, or constant
|
||||||
|
declaration, and no test or benchmark functions.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<h2 id="index">Index</h2>
|
||||||
|
<!-- Table of contents for API; must be named manual-nav to turn off auto nav. -->
|
||||||
|
<div id="manual-nav">
|
||||||
|
<dl>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<dd><a href="#Main">func Main(matchString func(pat, str string) (bool, error), tests []InternalTest, benchmarks []InternalBenchmark, examples []InternalExample)</a></dd>
|
||||||
|
|
||||||
|
|
||||||
|
<dd><a href="#RunBenchmarks">func RunBenchmarks(matchString func(pat, str string) (bool, error), benchmarks []InternalBenchmark)</a></dd>
|
||||||
|
|
||||||
|
|
||||||
|
<dd><a href="#RunExamples">func RunExamples(matchString func(pat, str string) (bool, error), examples []InternalExample) (ok bool)</a></dd>
|
||||||
|
|
||||||
|
|
||||||
|
<dd><a href="#RunTests">func RunTests(matchString func(pat, str string) (bool, error), tests []InternalTest) (ok bool)</a></dd>
|
||||||
|
|
||||||
|
|
||||||
|
<dd><a href="#Short">func Short() bool</a></dd>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<dd><a href="#B">type B</a></dd>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<dd> <a href="#B.Error">func (c *B) Error(args ...interface{})</a></dd>
|
||||||
|
|
||||||
|
|
||||||
|
<dd> <a href="#B.Errorf">func (c *B) Errorf(format string, args ...interface{})</a></dd>
|
||||||
|
|
||||||
|
|
||||||
|
<dd> <a href="#B.Fail">func (c *B) Fail()</a></dd>
|
||||||
|
|
||||||
|
|
||||||
|
<dd> <a href="#B.FailNow">func (c *B) FailNow()</a></dd>
|
||||||
|
|
||||||
|
|
||||||
|
<dd> <a href="#B.Failed">func (c *B) Failed() bool</a></dd>
|
||||||
|
|
||||||
|
|
||||||
|
<dd> <a href="#B.Fatal">func (c *B) Fatal(args ...interface{})</a></dd>
|
||||||
|
|
||||||
|
|
||||||
|
<dd> <a href="#B.Fatalf">func (c *B) Fatalf(format string, args ...interface{})</a></dd>
|
||||||
|
|
||||||
|
|
||||||
|
<dd> <a href="#B.Log">func (c *B) Log(args ...interface{})</a></dd>
|
||||||
|
|
||||||
|
|
||||||
|
<dd> <a href="#B.Logf">func (c *B) Logf(format string, args ...interface{})</a></dd>
|
||||||
|
|
||||||
|
|
||||||
|
<dd> <a href="#B.ResetTimer">func (b *B) ResetTimer()</a></dd>
|
||||||
|
|
||||||
|
|
||||||
|
<dd> <a href="#B.SetBytes">func (b *B) SetBytes(n int64)</a></dd>
|
||||||
|
|
||||||
|
|
||||||
|
<dd> <a href="#B.StartTimer">func (b *B) StartTimer()</a></dd>
|
||||||
|
|
||||||
|
|
||||||
|
<dd> <a href="#B.StopTimer">func (b *B) StopTimer()</a></dd>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<dd><a href="#BenchmarkResult">type BenchmarkResult</a></dd>
|
||||||
|
|
||||||
|
|
||||||
|
<dd> <a href="#Benchmark">func Benchmark(f func(b *B)) BenchmarkResult</a></dd>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<dd> <a href="#BenchmarkResult.NsPerOp">func (r BenchmarkResult) NsPerOp() int64</a></dd>
|
||||||
|
|
||||||
|
|
||||||
|
<dd> <a href="#BenchmarkResult.String">func (r BenchmarkResult) String() string</a></dd>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<dd><a href="#InternalBenchmark">type InternalBenchmark</a></dd>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<dd><a href="#InternalExample">type InternalExample</a></dd>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<dd><a href="#InternalTest">type InternalTest</a></dd>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<dd><a href="#T">type T</a></dd>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<dd> <a href="#T.Error">func (c *T) Error(args ...interface{})</a></dd>
|
||||||
|
|
||||||
|
|
||||||
|
<dd> <a href="#T.Errorf">func (c *T) Errorf(format string, args ...interface{})</a></dd>
|
||||||
|
|
||||||
|
|
||||||
|
<dd> <a href="#T.Fail">func (c *T) Fail()</a></dd>
|
||||||
|
|
||||||
|
|
||||||
|
<dd> <a href="#T.FailNow">func (c *T) FailNow()</a></dd>
|
||||||
|
|
||||||
|
|
||||||
|
<dd> <a href="#T.Failed">func (c *T) Failed() bool</a></dd>
|
||||||
|
|
||||||
|
|
||||||
|
<dd> <a href="#T.Fatal">func (c *T) Fatal(args ...interface{})</a></dd>
|
||||||
|
|
||||||
|
|
||||||
|
<dd> <a href="#T.Fatalf">func (c *T) Fatalf(format string, args ...interface{})</a></dd>
|
||||||
|
|
||||||
|
|
||||||
|
<dd> <a href="#T.Log">func (c *T) Log(args ...interface{})</a></dd>
|
||||||
|
|
||||||
|
|
||||||
|
<dd> <a href="#T.Logf">func (c *T) Logf(format string, args ...interface{})</a></dd>
|
||||||
|
|
||||||
|
|
||||||
|
<dd> <a href="#T.Parallel">func (t *T) Parallel()</a></dd>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</dl>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<h4>Package files</h4>
|
||||||
|
<p>
|
||||||
|
<span style="font-size:90%">
|
||||||
|
|
||||||
|
<a href="/src/pkg/testing/benchmark.go">benchmark.go</a>
|
||||||
|
|
||||||
|
<a href="/src/pkg/testing/example.go">example.go</a>
|
||||||
|
|
||||||
|
<a href="/src/pkg/testing/testing.go">testing.go</a>
|
||||||
|
|
||||||
|
</span>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<h2 id="Main">func <a href="/src/pkg/testing/testing.go?s=9750:9890#L268">Main</a></h2>
|
||||||
|
<pre>func Main(matchString func(pat, str string) (bool, error), tests []InternalTest, benchmarks []InternalBenchmark, examples []InternalExample)</pre>
|
||||||
|
<p>
|
||||||
|
An internal function but exported because it is cross-package; part of the implementation
|
||||||
|
of the "go test" command.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<h2 id="RunBenchmarks">func <a href="/src/pkg/testing/benchmark.go?s=5365:5464#L207">RunBenchmarks</a></h2>
|
||||||
|
<pre>func RunBenchmarks(matchString func(pat, str string) (bool, error), benchmarks []InternalBenchmark)</pre>
|
||||||
|
<p>
|
||||||
|
An internal function but exported because it is cross-package; part of the implementation
|
||||||
|
of the "go test" command.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<h2 id="RunExamples">func <a href="/src/pkg/testing/example.go?s=314:417#L12">RunExamples</a></h2>
|
||||||
|
<pre>func RunExamples(matchString func(pat, str string) (bool, error), examples []InternalExample) (ok bool)</pre>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<h2 id="RunTests">func <a href="/src/pkg/testing/testing.go?s=10486:10580#L297">RunTests</a></h2>
|
||||||
|
<pre>func RunTests(matchString func(pat, str string) (bool, error), tests []InternalTest) (ok bool)</pre>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<h2 id="Short">func <a href="/src/pkg/testing/testing.go?s=4859:4876#L117">Short</a></h2>
|
||||||
|
<pre>func Short() bool</pre>
|
||||||
|
<p>
|
||||||
|
Short reports whether the -test.short flag is set.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<h2 id="B">type <a href="/src/pkg/testing/benchmark.go?s=743:872#L17">B</a></h2>
|
||||||
|
<pre>type B struct {
|
||||||
|
N int
|
||||||
|
<span class="comment">// contains filtered or unexported fields</span>
|
||||||
|
}</pre>
|
||||||
|
<p>
|
||||||
|
B is a type passed to Benchmark functions to manage benchmark
|
||||||
|
timing and to specify the number of iterations to run.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<h3 id="B.Error">func (*B) <a href="/src/pkg/testing/testing.go?s=8110:8153#L209">Error</a></h3>
|
||||||
|
<pre>func (c *B) Error(args ...interface{})</pre>
|
||||||
|
<p>
|
||||||
|
Error is equivalent to Log() followed by Fail().
|
||||||
|
</p>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<h3 id="B.Errorf">func (*B) <a href="/src/pkg/testing/testing.go?s=8253:8312#L215">Errorf</a></h3>
|
||||||
|
<pre>func (c *B) Errorf(format string, args ...interface{})</pre>
|
||||||
|
<p>
|
||||||
|
Errorf is equivalent to Logf() followed by Fail().
|
||||||
|
</p>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<h3 id="B.Fail">func (*B) <a href="/src/pkg/testing/testing.go?s=6270:6293#L163">Fail</a></h3>
|
||||||
|
<pre>func (c *B) Fail()</pre>
|
||||||
|
<p>
|
||||||
|
Fail marks the function as having failed but continues execution.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<h3 id="B.FailNow">func (*B) <a href="/src/pkg/testing/testing.go?s=6548:6574#L170">FailNow</a></h3>
|
||||||
|
<pre>func (c *B) FailNow()</pre>
|
||||||
|
<p>
|
||||||
|
FailNow marks the function as having failed and stops its execution.
|
||||||
|
Execution will continue at the next test or benchmark.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<h3 id="B.Failed">func (*B) <a href="/src/pkg/testing/testing.go?s=6366:6396#L166">Failed</a></h3>
|
||||||
|
<pre>func (c *B) Failed() bool</pre>
|
||||||
|
<p>
|
||||||
|
Failed returns whether the function has failed.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<h3 id="B.Fatal">func (*B) <a href="/src/pkg/testing/testing.go?s=8420:8463#L221">Fatal</a></h3>
|
||||||
|
<pre>func (c *B) Fatal(args ...interface{})</pre>
|
||||||
|
<p>
|
||||||
|
Fatal is equivalent to Log() followed by FailNow().
|
||||||
|
</p>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<h3 id="B.Fatalf">func (*B) <a href="/src/pkg/testing/testing.go?s=8569:8628#L227">Fatalf</a></h3>
|
||||||
|
<pre>func (c *B) Fatalf(format string, args ...interface{})</pre>
|
||||||
|
<p>
|
||||||
|
Fatalf is equivalent to Logf() followed by FailNow().
|
||||||
|
</p>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<h3 id="B.Log">func (*B) <a href="/src/pkg/testing/testing.go?s=7763:7804#L202">Log</a></h3>
|
||||||
|
<pre>func (c *B) Log(args ...interface{})</pre>
|
||||||
|
<p>
|
||||||
|
Log formats its arguments using default formatting, analogous to Println(),
|
||||||
|
and records the text in the error log.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<h3 id="B.Logf">func (*B) <a href="/src/pkg/testing/testing.go?s=7959:8016#L206">Logf</a></h3>
|
||||||
|
<pre>func (c *B) Logf(format string, args ...interface{})</pre>
|
||||||
|
<p>
|
||||||
|
Logf formats its arguments according to the format, analogous to Printf(),
|
||||||
|
and records the text in the error log.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<h3 id="B.ResetTimer">func (*B) <a href="/src/pkg/testing/benchmark.go?s=1503:1527#L48">ResetTimer</a></h3>
|
||||||
|
<pre>func (b *B) ResetTimer()</pre>
|
||||||
|
<p>
|
||||||
|
ResetTimer sets the elapsed benchmark time to zero.
|
||||||
|
It does not affect whether the timer is running.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<h3 id="B.SetBytes">func (*B) <a href="/src/pkg/testing/benchmark.go?s=1728:1757#L57">SetBytes</a></h3>
|
||||||
|
<pre>func (b *B) SetBytes(n int64)</pre>
|
||||||
|
<p>
|
||||||
|
SetBytes records the number of bytes processed in a single operation.
|
||||||
|
If this is called, the benchmark will report ns/op and MB/s.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<h3 id="B.StartTimer">func (*B) <a href="/src/pkg/testing/benchmark.go?s=1047:1071#L29">StartTimer</a></h3>
|
||||||
|
<pre>func (b *B) StartTimer()</pre>
|
||||||
|
<p>
|
||||||
|
StartTimer starts timing a test. This function is called automatically
|
||||||
|
before a benchmark starts, but it can also used to resume timing after
|
||||||
|
a call to StopTimer.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<h3 id="B.StopTimer">func (*B) <a href="/src/pkg/testing/benchmark.go?s=1288:1311#L39">StopTimer</a></h3>
|
||||||
|
<pre>func (b *B) StopTimer()</pre>
|
||||||
|
<p>
|
||||||
|
StopTimer stops timing a test. This can be used to pause the timer
|
||||||
|
while performing complex initialization that you don't
|
||||||
|
want to measure.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<h2 id="BenchmarkResult">type <a href="/src/pkg/testing/benchmark.go?s=4206:4391#L165">BenchmarkResult</a></h2>
|
||||||
|
<pre>type BenchmarkResult struct {
|
||||||
|
N int <span class="comment">// The number of iterations.</span>
|
||||||
|
T time.Duration <span class="comment">// The total time taken.</span>
|
||||||
|
Bytes int64 <span class="comment">// Bytes processed in one iteration.</span>
|
||||||
|
}</pre>
|
||||||
|
<p>
|
||||||
|
The results of a benchmark run.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<h3 id="Benchmark">func <a href="/src/pkg/testing/benchmark.go?s=7545:7589#L275">Benchmark</a></h3>
|
||||||
|
<pre>func Benchmark(f func(b *B)) BenchmarkResult</pre>
|
||||||
|
<p>
|
||||||
|
Benchmark benchmarks a single function. Useful for creating
|
||||||
|
custom benchmarks that do not use the "go test" command.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<h3 id="BenchmarkResult.NsPerOp">func (BenchmarkResult) <a href="/src/pkg/testing/benchmark.go?s=4393:4433#L171">NsPerOp</a></h3>
|
||||||
|
<pre>func (r BenchmarkResult) NsPerOp() int64</pre>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<h3 id="BenchmarkResult.String">func (BenchmarkResult) <a href="/src/pkg/testing/benchmark.go?s=4677:4717#L185">String</a></h3>
|
||||||
|
<pre>func (r BenchmarkResult) String() string</pre>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<h2 id="InternalBenchmark">type <a href="/src/pkg/testing/benchmark.go?s=555:618#L10">InternalBenchmark</a></h2>
|
||||||
|
<pre>type InternalBenchmark struct {
|
||||||
|
Name string
|
||||||
|
F func(b *B)
|
||||||
|
}</pre>
|
||||||
|
<p>
|
||||||
|
An internal type but exported because it is cross-package; part of the implementation
|
||||||
|
of the "go test" command.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<h2 id="InternalExample">type <a href="/src/pkg/testing/example.go?s=236:312#L6">InternalExample</a></h2>
|
||||||
|
<pre>type InternalExample struct {
|
||||||
|
Name string
|
||||||
|
F func()
|
||||||
|
Output string
|
||||||
|
}</pre>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<h2 id="InternalTest">type <a href="/src/pkg/testing/testing.go?s=9065:9121#L241">InternalTest</a></h2>
|
||||||
|
<pre>type InternalTest struct {
|
||||||
|
Name string
|
||||||
|
F func(*T)
|
||||||
|
}</pre>
|
||||||
|
<p>
|
||||||
|
An internal type but exported because it is cross-package; part of the implementation
|
||||||
|
of the "go test" command.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<h2 id="T">type <a href="/src/pkg/testing/testing.go?s=6070:6199#L156">T</a></h2>
|
||||||
|
<pre>type T struct {
|
||||||
|
<span class="comment">// contains filtered or unexported fields</span>
|
||||||
|
}</pre>
|
||||||
|
<p>
|
||||||
|
T is a type passed to Test functions to manage test state and support formatted test logs.
|
||||||
|
Logs are accumulated during execution and dumped to standard error when done.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<h3 id="T.Error">func (*T) <a href="/src/pkg/testing/testing.go?s=8110:8153#L209">Error</a></h3>
|
||||||
|
<pre>func (c *T) Error(args ...interface{})</pre>
|
||||||
|
<p>
|
||||||
|
Error is equivalent to Log() followed by Fail().
|
||||||
|
</p>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<h3 id="T.Errorf">func (*T) <a href="/src/pkg/testing/testing.go?s=8253:8312#L215">Errorf</a></h3>
|
||||||
|
<pre>func (c *T) Errorf(format string, args ...interface{})</pre>
|
||||||
|
<p>
|
||||||
|
Errorf is equivalent to Logf() followed by Fail().
|
||||||
|
</p>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<h3 id="T.Fail">func (*T) <a href="/src/pkg/testing/testing.go?s=6270:6293#L163">Fail</a></h3>
|
||||||
|
<pre>func (c *T) Fail()</pre>
|
||||||
|
<p>
|
||||||
|
Fail marks the function as having failed but continues execution.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<h3 id="T.FailNow">func (*T) <a href="/src/pkg/testing/testing.go?s=6548:6574#L170">FailNow</a></h3>
|
||||||
|
<pre>func (c *T) FailNow()</pre>
|
||||||
|
<p>
|
||||||
|
FailNow marks the function as having failed and stops its execution.
|
||||||
|
Execution will continue at the next test or benchmark.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<h3 id="T.Failed">func (*T) <a href="/src/pkg/testing/testing.go?s=6366:6396#L166">Failed</a></h3>
|
||||||
|
<pre>func (c *T) Failed() bool</pre>
|
||||||
|
<p>
|
||||||
|
Failed returns whether the function has failed.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<h3 id="T.Fatal">func (*T) <a href="/src/pkg/testing/testing.go?s=8420:8463#L221">Fatal</a></h3>
|
||||||
|
<pre>func (c *T) Fatal(args ...interface{})</pre>
|
||||||
|
<p>
|
||||||
|
Fatal is equivalent to Log() followed by FailNow().
|
||||||
|
</p>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<h3 id="T.Fatalf">func (*T) <a href="/src/pkg/testing/testing.go?s=8569:8628#L227">Fatalf</a></h3>
|
||||||
|
<pre>func (c *T) Fatalf(format string, args ...interface{})</pre>
|
||||||
|
<p>
|
||||||
|
Fatalf is equivalent to Logf() followed by FailNow().
|
||||||
|
</p>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<h3 id="T.Log">func (*T) <a href="/src/pkg/testing/testing.go?s=7763:7804#L202">Log</a></h3>
|
||||||
|
<pre>func (c *T) Log(args ...interface{})</pre>
|
||||||
|
<p>
|
||||||
|
Log formats its arguments using default formatting, analogous to Println(),
|
||||||
|
and records the text in the error log.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<h3 id="T.Logf">func (*T) <a href="/src/pkg/testing/testing.go?s=7959:8016#L206">Logf</a></h3>
|
||||||
|
<pre>func (c *T) Logf(format string, args ...interface{})</pre>
|
||||||
|
<p>
|
||||||
|
Logf formats its arguments according to the format, analogous to Printf(),
|
||||||
|
and records the text in the error log.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<h3 id="T.Parallel">func (*T) <a href="/src/pkg/testing/testing.go?s=8809:8831#L234">Parallel</a></h3>
|
||||||
|
<pre>func (t *T) Parallel()</pre>
|
||||||
|
<p>
|
||||||
|
Parallel signals that this test is to be run in parallel with (and only with)
|
||||||
|
other parallel tests in this CPU group.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<h2 id="subdirectories">Subdirectories</h2>
|
||||||
|
|
||||||
|
<table class="dir">
|
||||||
|
<tr>
|
||||||
|
<th>Name</th>
|
||||||
|
<th> </th>
|
||||||
|
<th style="text-align: left; width: auto">Synopsis</th>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
<tr>
|
||||||
|
<td><a href="..">..</a></td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<tr>
|
||||||
|
<td class="name"><a href="iotest">iotest</a></td>
|
||||||
|
<td> </td>
|
||||||
|
<td style="width: auto">Package iotest implements Readers and Writers useful mainly for testing.</td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<tr>
|
||||||
|
<td class="name"><a href="quick">quick</a></td>
|
||||||
|
<td> </td>
|
||||||
|
<td style="width: auto">Package quick implements utility functions to help with black box testing.</td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
|
||||||
|
</table>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="footer">
|
||||||
|
Build version go1.0.2.<br>
|
||||||
|
Except as <a href="http://code.google.com/policies.html#restrictions">noted</a>,
|
||||||
|
the content of this page is licensed under the
|
||||||
|
Creative Commons Attribution 3.0 License,
|
||||||
|
and code is licensed under a <a href="/LICENSE">BSD license</a>.<br>
|
||||||
|
<a href="/doc/tos.html">Terms of Service</a> |
|
||||||
|
<a href="http://www.google.com/intl/en/privacy/privacy-policy.html">Privacy Policy</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script type="text/javascript">
|
||||||
|
(function() {
|
||||||
|
var ga = document.createElement("script"); ga.type = "text/javascript"; ga.async = true;
|
||||||
|
ga.src = ("https:" == document.location.protocol ? "https://ssl" : "http://www") + ".google-analytics.com/ga.js";
|
||||||
|
var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(ga, s);
|
||||||
|
})();
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
<script type="text/javascript">
|
||||||
|
(function() {
|
||||||
|
var po = document.createElement('script'); po.type = 'text/javascript'; po.async = true;
|
||||||
|
po.src = 'https://apis.google.com/js/plusone.js';
|
||||||
|
var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(po, s);
|
||||||
|
})();
|
||||||
|
</script>
|
||||||
|
</html>
|
||||||
|
|
1214
Godeps/_workspace/src/github.com/PuerkitoBio/goquery/testdata/gowiki.html
generated
vendored
Normal file
1214
Godeps/_workspace/src/github.com/PuerkitoBio/goquery/testdata/gowiki.html
generated
vendored
Normal file
File diff suppressed because it is too large
Load diff
413
Godeps/_workspace/src/github.com/PuerkitoBio/goquery/testdata/metalreview.html
generated
vendored
Normal file
413
Godeps/_workspace/src/github.com/PuerkitoBio/goquery/testdata/metalreview.html
generated
vendored
Normal file
|
@ -0,0 +1,413 @@
|
||||||
|
|
||||||
|
|
||||||
|
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||||
|
|
||||||
|
<html xmlns="http://www.w3.org/1999/xhtml" >
|
||||||
|
<head><meta http-equiv="X-UA-Compatible" content="IE=8" />
|
||||||
|
|
||||||
|
<meta name="keywords" content="metal, reviews, metalreview, metalreviews, heavy, rock, review, music, blogs, forums, community" />
|
||||||
|
<meta name="description" content="Critical heavy metal album and dvd reviews, written by professional writers. Large community with forums, blogs, photos and commenting system." />
|
||||||
|
|
||||||
|
<title>
|
||||||
|
|
||||||
|
|
||||||
|
Metal Reviews, News, Blogs, Interviews and Community | Metal Review
|
||||||
|
|
||||||
|
|
||||||
|
</title><link rel="stylesheet" type="text/css" href="/Content/Css/reset-fonts-grids.css" /><link rel="stylesheet" type="text/css" href="/Content/Css/base.css" /><link rel="stylesheet" type="text/css" href="/Content/Css/core.css" /><link rel="stylesheet" type="text/css" href="/Content/Css/wt-rotator.css" />
|
||||||
|
<script src="/Scripts/jquery-1.4.2.min.js" type="text/javascript"></script>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<script type="text/javascript">
|
||||||
|
var _comscore = _comscore || [];
|
||||||
|
_comscore.push({ c1: "2", c2: "9290245" });
|
||||||
|
(function () {
|
||||||
|
var s = document.createElement("script"), el = document.getElementsByTagName("script")[0]; s.async = true;
|
||||||
|
s.src = (document.location.protocol == "https:" ? "https://sb" : "http://b") + ".scorecardresearch.com/beacon.js";
|
||||||
|
el.parentNode.insertBefore(s, el);
|
||||||
|
})();
|
||||||
|
</script>
|
||||||
|
<noscript>
|
||||||
|
<img src="http://b.scorecardresearch.com/p?c1=2&c2=9290245&cv=2.0&cj=1" />
|
||||||
|
</noscript>
|
||||||
|
|
||||||
|
|
||||||
|
<div id="doc2" class="yui-t7">
|
||||||
|
<div id="hd">
|
||||||
|
|
||||||
|
|
||||||
|
<div id="main-logo"><a href="/" title="Home"><img src="/Content/Images/metal-review-logo.png" alt="Metal Review Home" border="0" /></a></div>
|
||||||
|
<div id="leaderboard-banner">
|
||||||
|
|
||||||
|
<script language="javascript" type="text/javascript"><!--
|
||||||
|
document.write('<scr' + 'ipt language="javascript1.1" src="http://adserver.adtechus.com/addyn/3.0/5110/73085/0/225/ADTECH;loc=100;target=_blank;key=key1+key2+key3+key4;grp=[group];misc=' + new Date().getTime() + '"></scri' + 'pt>');
|
||||||
|
//-->
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<noscript>
|
||||||
|
<a href="http://adserver.adtechus.com/adlink/3.0/5110/73085/0/225/ADTECH;loc=300;key=key1+key2+key3+key4;grp=[group]" target="_blank">
|
||||||
|
<img src="http://adserver.adtechus.com/adserv/3.0/5110/73085/0/225/ADTECH;loc=300;key=key1+key2+key3+key4;grp=[group]" border="0" width="728" height="90" />
|
||||||
|
</a>
|
||||||
|
</noscript>
|
||||||
|
</div>
|
||||||
|
<div id="header-menu-container">
|
||||||
|
<div id="header-menu">
|
||||||
|
<a href="/reviews/browse">REVIEWS</a>
|
||||||
|
<a href="http://community2.metalreview.com/blogs/editorials/default.aspx">FEATURES</a>
|
||||||
|
<a href="/artists/browse">ARTISTS</a>
|
||||||
|
<a href="/reviews/pipeline">PIPELINE</a>
|
||||||
|
<a href="http://community2.metalreview.com/forums">FORUMS</a>
|
||||||
|
<a href="http://community2.metalreview.com/blogs/">BLOGS</a>
|
||||||
|
<a href="/aboutus">ABOUT US</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="sign-in"><a href="https://metalreview.com/account/signin">SIGN IN</a> | <a href="/account/register">JOIN US</a></div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div id="bd">
|
||||||
|
|
||||||
|
<div id="yui-main">
|
||||||
|
<div class="yui-b">
|
||||||
|
<div class="yui-g">
|
||||||
|
<div class="yui-u first">
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<script src="/Scripts/jquery.wt-rotator.min.js" type="text/javascript"></script>
|
||||||
|
<script src="/Scripts/jquery.wt-rotator-initialize.js" type="text/javascript"></script>
|
||||||
|
<div id="review-showcase-wrapper">
|
||||||
|
<h2 id="showcase-heading">Reviews</h2>
|
||||||
|
<div id="review-showcase">
|
||||||
|
<div class="container">
|
||||||
|
<div class="wt-rotator">
|
||||||
|
<a href="#"></a>
|
||||||
|
<div class="desc">
|
||||||
|
</div>
|
||||||
|
<div class="preloader">
|
||||||
|
</div>
|
||||||
|
<div class="c-panel">
|
||||||
|
<div class="buttons">
|
||||||
|
<div class="prev-btn">
|
||||||
|
</div>
|
||||||
|
<div class="play-btn">
|
||||||
|
</div>
|
||||||
|
<div class="next-btn">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="thumbnails">
|
||||||
|
<ul>
|
||||||
|
|
||||||
|
<li><a href="artist.photo?mrx=4641" title="Serpentine Path - Serpentine Path"></a><a href="/reviews/6844/serpentine-path-serpentine-path"></a>
|
||||||
|
<p style="top: 130px; left: 22px; width: 305px; height:60px;">
|
||||||
|
<img class="rotator-cover-art" src="album.cover?art=6844" alt='Serpentine Path - Serpentine Path' title='Serpentine Path - Serpentine Path' />
|
||||||
|
<span class="title"><strong>Serpentine Path</strong></span><br />
|
||||||
|
Serpentine Path<br />
|
||||||
|
|
||||||
|
</p>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li><a href="artist.photo?mrx=4635" title="Hunter's Ground - No God But the Wild"></a><a href="/reviews/6830/hunters-ground-no-god-but-the-wild"></a>
|
||||||
|
<p style="top: 130px; left: 22px; width: 305px; height:60px;">
|
||||||
|
<img class="rotator-cover-art" src="album.cover?art=6830" alt='Hunter's Ground - No God But the Wild' title='Hunter's Ground - No God But the Wild' />
|
||||||
|
<span class="title"><strong>Hunter's Ground</strong></span><br />
|
||||||
|
No God But the Wild<br />
|
||||||
|
|
||||||
|
</p>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li><a href="artist.photo?mrx=1035" title="Blut Aus Nord - 777 - Cosmosophy"></a><a href="/reviews/6829/blut-aus-nord-777---cosmosophy"></a>
|
||||||
|
<p style="top: 130px; left: 22px; width: 305px; height:60px;">
|
||||||
|
<img class="rotator-cover-art" src="album.cover?art=6829" alt='Blut Aus Nord - 777 - Cosmosophy' title='Blut Aus Nord - 777 - Cosmosophy' />
|
||||||
|
<span class="title"><strong>Blut Aus Nord</strong></span><br />
|
||||||
|
777 - Cosmosophy<br />
|
||||||
|
<a href="/tags/10/black"><span class="tag">Black</span></a>
|
||||||
|
</p>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li><a href="artist.photo?mrx=1217" title="Ufomammut - Oro: Opus Alter"></a><a href="/reviews/6835/ufomammut-oro--opus-alter"></a>
|
||||||
|
<p style="top: 130px; left: 22px; width: 305px; height:60px;">
|
||||||
|
<img class="rotator-cover-art" src="album.cover?art=6835" alt='Ufomammut - Oro: Opus Alter' title='Ufomammut - Oro: Opus Alter' />
|
||||||
|
<span class="title"><strong>Ufomammut</strong></span><br />
|
||||||
|
Oro: Opus Alter<br />
|
||||||
|
<a href="/tags/2/doom"><span class="tag">Doom</span></a>
|
||||||
|
</p>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li><a href="artist.photo?mrx=4590" title="Resurgency - False Enlightenment"></a><a href="/reviews/6746/resurgency-false-enlightenment"></a>
|
||||||
|
<p style="top: 130px; left: 22px; width: 305px; height:60px;">
|
||||||
|
<img class="rotator-cover-art" src="album.cover?art=6746" alt='Resurgency - False Enlightenment' title='Resurgency - False Enlightenment' />
|
||||||
|
<span class="title"><strong>Resurgency</strong></span><br />
|
||||||
|
False Enlightenment<br />
|
||||||
|
<a href="/tags/1/death"><span class="tag">Death</span></a>
|
||||||
|
</p>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li><a href="artist.photo?mrx=1360" title="Morgoth - Cursed to Live"></a><a href="/reviews/6800/morgoth-cursed-to-live"></a>
|
||||||
|
<p style="top: 130px; left: 22px; width: 305px; height:60px;">
|
||||||
|
<img class="rotator-cover-art" src="album.cover?art=6800" alt='Morgoth - Cursed to Live' title='Morgoth - Cursed to Live' />
|
||||||
|
<span class="title"><strong>Morgoth</strong></span><br />
|
||||||
|
Cursed to Live<br />
|
||||||
|
<a href="/tags/1/death"><span class="tag">Death</span></a><a href="/tags/31/live"><span class="tag">Live</span></a>
|
||||||
|
</p>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li><a href="artist.photo?mrx=3879" title="Krallice - Years Past Matter"></a><a href="/reviews/6853/krallice-years-past-matter"></a>
|
||||||
|
<p style="top: 130px; left: 22px; width: 305px; height:60px;">
|
||||||
|
<img class="rotator-cover-art" src="album.cover?art=6853" alt='Krallice - Years Past Matter' title='Krallice - Years Past Matter' />
|
||||||
|
<span class="title"><strong>Krallice</strong></span><br />
|
||||||
|
Years Past Matter<br />
|
||||||
|
<a href="/tags/10/black"><span class="tag">Black</span></a>
|
||||||
|
</p>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li><a href="artist.photo?mrx=4243" title="Murder Construct - Results"></a><a href="/reviews/6782/murder-construct-results"></a>
|
||||||
|
<p style="top: 130px; left: 22px; width: 305px; height:60px;">
|
||||||
|
<img class="rotator-cover-art" src="album.cover?art=6782" alt='Murder Construct - Results' title='Murder Construct - Results' />
|
||||||
|
<span class="title"><strong>Murder Construct</strong></span><br />
|
||||||
|
Results<br />
|
||||||
|
<a href="/tags/13/grindcore"><span class="tag">Grindcore</span></a>
|
||||||
|
</p>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li><a href="artist.photo?mrx=251" title="Grave - Endless Procession of Souls"></a><a href="/reviews/6834/grave-endless-procession-of-souls"></a>
|
||||||
|
<p style="top: 130px; left: 22px; width: 305px; height:60px;">
|
||||||
|
<img class="rotator-cover-art" src="album.cover?art=6834" alt='Grave - Endless Procession of Souls' title='Grave - Endless Procession of Souls' />
|
||||||
|
<span class="title"><strong>Grave</strong></span><br />
|
||||||
|
Endless Procession of Souls<br />
|
||||||
|
<a href="/tags/1/death"><span class="tag">Death</span></a>
|
||||||
|
</p>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li><a href="artist.photo?mrx=3508" title="Master - The New Elite"></a><a href="/reviews/6774/master-the-new-elite"></a>
|
||||||
|
<p style="top: 130px; left: 22px; width: 305px; height:60px;">
|
||||||
|
<img class="rotator-cover-art" src="album.cover?art=6774" alt='Master - The New Elite' title='Master - The New Elite' />
|
||||||
|
<span class="title"><strong>Master</strong></span><br />
|
||||||
|
The New Elite<br />
|
||||||
|
<a href="/tags/1/death"><span class="tag">Death</span></a>
|
||||||
|
</p>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div id="showcase-all-artist-albums">
|
||||||
|
<a href="/reviews/6844/serpentine-path-serpentine-path"><img src="album.cover?art=6844" alt="Serpentine Path - Serpentine Path" /></a><a href="/reviews/6830/hunters-ground-no-god-but-the-wild"><img src="album.cover?art=6830" alt="Hunter's Ground - No God But the Wild" /></a><a href="/reviews/6829/blut-aus-nord-777---cosmosophy"><img src="album.cover?art=6829" alt="Blut Aus Nord - 777 - Cosmosophy" /></a><a href="/reviews/6835/ufomammut-oro--opus-alter"><img src="album.cover?art=6835" alt="Ufomammut - Oro: Opus Alter" /></a><a href="/reviews/6746/resurgency-false-enlightenment"><img src="album.cover?art=6746" alt="Resurgency - False Enlightenment" /></a><a href="/reviews/6800/morgoth-cursed-to-live"><img src="album.cover?art=6800" alt="Morgoth - Cursed to Live" /></a><a href="/reviews/6853/krallice-years-past-matter"><img src="album.cover?art=6853" alt="Krallice - Years Past Matter" /></a><a href="/reviews/6782/murder-construct-results"><img src="album.cover?art=6782" alt="Murder Construct - Results" /></a><a href="/reviews/6834/grave-endless-procession-of-souls"><img src="album.cover?art=6834" alt="Grave - Endless Procession of Souls" /></a><a href="/reviews/6774/master-the-new-elite"><img src="album.cover?art=6774" alt="Master - The New Elite" /></a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="yui-u">
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<div id="feature-feed">
|
||||||
|
<h2>Features</h2>
|
||||||
|
<div class="feature-feed-line"><a href="http://community2.metalreview.com/blogs/editorials/archive/2012/08/15/corsair-interview.aspx"><span class="feature-link"><strong>Release The SkyKrakken: Corsair Interview</strong></span></a><br /><span class="publish-date">8/15/2012 by JW</span><img align="left" src="http://community2.metalreview.com/cfs-file.ashx/__key/CommunityServer.Components.Avatars/00.00.00.21.25/4TMR3E1CWERK.jpg" alt="JW's Avatar" width="36px" height="40px" border="0" /></div>
|
||||||
|
<div class="feature-feed-line"><a href="http://community2.metalreview.com/blogs/editorials/archive/2012/08/09/riffology-kreative-evolution-part-iii.aspx"><span class="feature-link"><strong>Riffology: Kreative Evolution, Part III</strong></span></a><br /><span class="publish-date">8/9/2012 by Achilles</span><img align="left" src="http://community2.metalreview.com/cfs-file.ashx/__key/CommunityServer.Components.Avatars/00.00.00.21.44/4THUGH622I68.jpg" alt="Achilles's Avatar" width="40px" height="39px" border="0" /></div>
|
||||||
|
<div class="feature-feed-line"><a href="http://community2.metalreview.com/blogs/editorials/archive/2012/08/02/reverend-s-bazaar-don-t-trend-on-me.aspx"><span class="feature-link"><strong>Reverend's Bazaar - Don't Trend On Me </strong></span></a><br /><span class="publish-date">8/2/2012 by Reverend Campbell</span><img align="left" src="http://community2.metalreview.com/cfs-file.ashx/__key/CommunityServer.Components.Avatars/00.00.00.21.18/4TM06FD0ND4G.png" alt="Reverend Campbell's Avatar" width="34px" height="40px" border="0" /></div>
|
||||||
|
<div class="feature-feed-line"><a href="http://community2.metalreview.com/blogs/editorials/archive/2012/08/01/grand-theft-metal-three-for-free.aspx"><span class="feature-link"><strong>Grand Theft Metal - Free Four All </strong></span></a><br /><span class="publish-date">8/2/2012 by Dave</span><img align="left" src="http://community2.metalreview.com/cfs-file.ashx/__key/CommunityServer.Components.Avatars/00.00.00.22.16/4TKJCJQ00VFO.jpg" alt="Dave's Avatar" width="33px" height="40px" border="0" /></div>
|
||||||
|
<div class="feature-feed-line"><a href="http://community2.metalreview.com/blogs/editorials/archive/2012/07/29/monday-with-moonspell-the-interview.aspx"><span class="feature-link"><strong>A Monday with Moonspell: The Interview</strong></span></a><br /><span class="publish-date">7/29/2012 by raetamacue</span><img align="left" src="http://community2.metalreview.com/cfs-file.ashx/__key/CommunityServer.Components.Avatars/00.00.00.71.26/4TLIHKLUSXF4.jpg" alt="raetamacue's Avatar" width="37px" height="40px" border="0" /></div>
|
||||||
|
<div class="feature-feed-line"><a href="http://community2.metalreview.com/blogs/editorials/archive/2012/07/26/riffology-kreative-evolution-part-ii.aspx"><span class="feature-link"><strong>Riffology: Kreative Evolution Part II</strong></span></a><br /><span class="publish-date">7/26/2012 by Achilles</span><img align="left" src="http://community2.metalreview.com/cfs-file.ashx/__key/CommunityServer.Components.Avatars/00.00.00.21.44/4THUGH622I68.jpg" alt="Achilles's Avatar" width="40px" height="39px" border="0" /></div>
|
||||||
|
<div class="feature-feed-line"><a href="http://community2.metalreview.com/blogs/editorials/archive/2012/07/24/shadow-kingdom-records-giveaway.aspx"><span class="feature-link"><strong>WINNERS ANNOUNCED -- Shadow Kingdom Records Give...</strong></span></a><br /><span class="publish-date">7/24/2012 by Metal Review</span><img align="left" src="http://community2.metalreview.com/cfs-file.ashx/__key/CommunityServer.Components.Avatars/00.00.00.59.06/4TFD2N58B7BS.png" alt="Metal Review's Avatar" width="34px" height="40px" border="0" /></div>
|
||||||
|
|
||||||
|
<br />
|
||||||
|
<a href="http://community2.metalreview.com/blogs/editorials/default.aspx"><strong>More Editorials</strong></a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="yui-b">
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<script src="/Scripts/jquery.cycle.all.min.js" type="text/javascript"></script>
|
||||||
|
<div id="slider-next-button"><img id="slider-next" src="/Content/Images/Backgrounds/rotator-next-button.png" alt="Goto Next Group" title="Goto Next Group" /></div>
|
||||||
|
<div id="slider-back-button"><img id="slider-back" src="/Content/Images/Backgrounds/rotator-back-button.png" alt="Goto Previous Group" title="Goto Previous Group" /></div>
|
||||||
|
<div id="latest-reviews-slider">
|
||||||
|
<div class="slider-row">
|
||||||
|
<div class="slider-item"><a href="/reviews/6795/midnight-complete-and-total-hell"><img src="album.cover?art=6795" alt="Midnight Complete and Total Hell" /><br /><strong>Midnight</strong><br /><em>Complete and Total Hell</em></a><div class="score">8.5</div></div>
|
||||||
|
<div class="slider-item"><a href="/reviews/6842/over-your-threshold-facticity"><img src="album.cover?art=6842" alt="Over Your Threshold Facticity" /><br /><strong>Over Your Threshold</strong><br /><em>Facticity</em></a><div class="score">6.0</div></div>
|
||||||
|
<div class="slider-item"><a href="/reviews/6813/nuclear-death-terror-chaos-reigns"><img src="album.cover?art=6813" alt="Nuclear Death Terror Chaos Reigns" /><br /><strong>Nuclear Death Terror</strong><br /><em>Chaos Reigns</em></a><div class="score">7.5</div></div>
|
||||||
|
<div class="slider-item"><a href="/reviews/6811/evoken-atra-mors"><img src="album.cover?art=6811" alt="Evoken Atra Mors" /><br /><strong>Evoken</strong><br /><em>Atra Mors</em></a><div class="score">9.5</div></div>
|
||||||
|
<div class="slider-item"><a href="/reviews/6807/blacklodge-machination"><img src="album.cover?art=6807" alt="Blacklodge MachinatioN" /><br /><strong>Blacklodge</strong><br /><em>MachinatioN</em></a><div class="score">5.5</div></div>
|
||||||
|
<div class="slider-item"><a href="/reviews/6832/prototype-catalyst"><img src="album.cover?art=6832" alt="Prototype Catalyst" /><br /><strong>Prototype</strong><br /><em>Catalyst</em></a><div class="score">8.0</div></div>
|
||||||
|
<div class="slider-item"><a href="/reviews/6822/hypnosia-horror-infernal"><img src="album.cover?art=6822" alt="Hypnosia Horror Infernal" /><br /><strong>Hypnosia</strong><br /><em>Horror Infernal</em></a><div class="score">7.0</div></div>
|
||||||
|
<div class="slider-item"><a href="/reviews/6787/om-advaitic-songs"><img src="album.cover?art=6787" alt="OM Advaitic Songs" /><br /><strong>OM</strong><br /><em>Advaitic Songs</em></a><div class="score">8.0</div></div>
|
||||||
|
<div class="slider-item"><a href="/reviews/6765/afgrund-the-age-of-dumb"><img src="album.cover?art=6765" alt="Afgrund The Age Of Dumb" /><br /><strong>Afgrund</strong><br /><em>The Age Of Dumb</em></a><div class="score">8.5</div></div>
|
||||||
|
<div class="slider-item"><a href="/reviews/6773/binah-hallucinating-in-resurrecture"><img src="album.cover?art=6773" alt="Binah Hallucinating in Resurrecture" /><br /><strong>Binah</strong><br /><em>Hallucinating in Resurrecture</em></a><div class="score">8.5</div></div>
|
||||||
|
</div>
|
||||||
|
<div class="slider-row">
|
||||||
|
<div class="slider-item"><a href="/reviews/6802/deiphago-satan-alpha-omega"><img src="album.cover?art=6802" alt="Deiphago Satan Alpha Omega" /><br /><strong>Deiphago</strong><br /><em>Satan Alpha Omega</em></a><div class="score">8.0</div></div>
|
||||||
|
<div class="slider-item"><a href="/reviews/6719/conan-monnos"><img src="album.cover?art=6719" alt="Conan Monnos" /><br /><strong>Conan</strong><br /><em>Monnos</em></a><div class="score">8.0</div></div>
|
||||||
|
<div class="slider-item"><a href="/reviews/6702/alaric-alaric-atriarch---split-lp"><img src="album.cover?art=6702" alt="Alaric Alaric/Atriarch - Split LP" /><br /><strong>Alaric</strong><br /><em>Alaric/Atriarch - Split LP</em></a><div class="score">8.5</div></div>
|
||||||
|
<div class="slider-item"><a href="/reviews/6780/coven-worship-new-gods-(reissue)"><img src="album.cover?art=6780" alt="Coven Worship New Gods (Reissue)" /><br /><strong>Coven</strong><br /><em>Worship New Gods (Reissue)</em></a><div class="score">5.0</div></div>
|
||||||
|
<div class="slider-item"><a href="/reviews/6831/the-foreshadowing-second-world"><img src="album.cover?art=6831" alt="The Foreshadowing Second World" /><br /><strong>The Foreshadowing</strong><br /><em>Second World</em></a><div class="score">5.5</div></div>
|
||||||
|
<div class="slider-item"><a href="/reviews/6815/nether-regions-into-the-breach"><img src="album.cover?art=6815" alt="Nether Regions Into The Breach" /><br /><strong>Nether Regions</strong><br /><em>Into The Breach</em></a><div class="score">7.0</div></div>
|
||||||
|
<div class="slider-item"><a href="/reviews/6824/agalloch-faustian-echoes"><img src="album.cover?art=6824" alt="Agalloch Faustian Echoes" /><br /><strong>Agalloch</strong><br /><em>Faustian Echoes</em></a><div class="score">9.0</div></div>
|
||||||
|
<div class="slider-item"><a href="/reviews/6805/a-forest-of-stars-a-shadowplay-for-yesterdays"><img src="album.cover?art=6805" alt="A Forest Of Stars A Shadowplay For Yesterdays" /><br /><strong>A Forest Of Stars</strong><br /><em>A Shadowplay For Yesterdays</em></a><div class="score">9.0</div></div>
|
||||||
|
<div class="slider-item"><a href="/reviews/6763/de-profundis-the-emptiness-within"><img src="album.cover?art=6763" alt="De Profundis The Emptiness Within" /><br /><strong>De Profundis</strong><br /><em>The Emptiness Within</em></a><div class="score">7.5</div></div>
|
||||||
|
<div class="slider-item"><a href="/reviews/6826/ozzy-osbourne-speak-of-the-devil"><img src="album.cover?art=6826" alt="Ozzy Osbourne Speak of the Devil" /><br /><strong>Ozzy Osbourne</strong><br /><em>Speak of the Devil</em></a><div class="score">7.5</div></div>
|
||||||
|
</div>
|
||||||
|
<div class="slider-row">
|
||||||
|
<div class="slider-item"><a href="/reviews/6825/testament-dark-roots-of-earth"><img src="album.cover?art=6825" alt="Testament Dark Roots of Earth" /><br /><strong>Testament</strong><br /><em>Dark Roots of Earth</em></a><div class="score">8.0</div></div>
|
||||||
|
<div class="slider-item"><a href="/reviews/6796/eagle-twin-the-feather-tipped-the-serpents-scale"><img src="album.cover?art=6796" alt="Eagle Twin The Feather Tipped The Serpent's Scale" /><br /><strong>Eagle Twin</strong><br /><em>The Feather Tipped The Serpent's Scale</em></a><div class="score">8.5</div></div>
|
||||||
|
<div class="slider-item"><a href="/reviews/6609/king-forged-by-satans-doctrine"><img src="album.cover?art=6609" alt="King Forged by Satan's Doctrine" /><br /><strong>King</strong><br /><em>Forged by Satan's Doctrine</em></a><div class="score">5.5</div></div>
|
||||||
|
<div class="slider-item"><a href="/reviews/6798/khors-wisdom-of-centuries"><img src="album.cover?art=6798" alt="Khors Wisdom of Centuries" /><br /><strong>Khors</strong><br /><em>Wisdom of Centuries</em></a><div class="score">8.5</div></div>
|
||||||
|
<div class="slider-item"><a href="/reviews/6776/samothrace-reverence-to-stone"><img src="album.cover?art=6776" alt="Samothrace Reverence To Stone" /><br /><strong>Samothrace</strong><br /><em>Reverence To Stone</em></a><div class="score">8.0</div></div>
|
||||||
|
<div class="slider-item"><a href="/reviews/6784/horseback-on-the-eclipse"><img src="album.cover?art=6784" alt="Horseback On the Eclipse" /><br /><strong>Horseback</strong><br /><em>On the Eclipse</em></a><div class="score">8.0</div></div>
|
||||||
|
<div class="slider-item"><a href="/reviews/6690/incoming-cerebral-overdrive-le-stelle--a-voyage-adrift"><img src="album.cover?art=6690" alt="Incoming Cerebral Overdrive Le Stelle: A Voyage Adrift" /><br /><strong>Incoming Cerebral Overdrive</strong><br /><em>Le Stelle: A Voyage Adrift</em></a><div class="score">7.5</div></div>
|
||||||
|
<div class="slider-item"><a href="/reviews/6658/struck-by-lightning-true-predation"><img src="album.cover?art=6658" alt="Struck By Lightning True Predation" /><br /><strong>Struck By Lightning</strong><br /><em>True Predation</em></a><div class="score">7.0</div></div>
|
||||||
|
<div class="slider-item"><a href="/reviews/6772/offending-age-of-perversion"><img src="album.cover?art=6772" alt="Offending Age of Perversion" /><br /><strong>Offending</strong><br /><em>Age of Perversion</em></a><div class="score">7.5</div></div>
|
||||||
|
<div class="slider-item"><a href="/reviews/6804/king-of-asgard----to-north"><img src="album.cover?art=6804" alt="King Of Asgard ...to North" /><br /><strong>King Of Asgard</strong><br /><em>...to North</em></a><div class="score">7.5</div></div>
|
||||||
|
</div>
|
||||||
|
<div class="slider-row">
|
||||||
|
<div class="slider-item"><a href="/reviews/6783/burning-love-rotten-thing-to-say"><img src="album.cover?art=6783" alt="Burning Love Rotten Thing to Say" /><br /><strong>Burning Love</strong><br /><em>Rotten Thing to Say</em></a><div class="score">7.0</div></div>
|
||||||
|
<div class="slider-item"><a href="/reviews/6770/high-on-fire-the-art-of-self-defense-(reissue)"><img src="album.cover?art=6770" alt="High On Fire The Art Of Self Defense (Reissue)" /><br /><strong>High On Fire</strong><br /><em>The Art Of Self Defense (Reissue)</em></a><div class="score">7.5</div></div>
|
||||||
|
<div class="slider-item"><a href="/reviews/6660/horseback-half-blood"><img src="album.cover?art=6660" alt="Horseback Half Blood" /><br /><strong>Horseback</strong><br /><em>Half Blood</em></a><div class="score">6.5</div></div>
|
||||||
|
<div class="slider-item"><a href="/reviews/6732/aldebaran-embracing-the-lightless-depths"><img src="album.cover?art=6732" alt="Aldebaran Embracing the Lightless Depths" /><br /><strong>Aldebaran</strong><br /><em>Embracing the Lightless Depths</em></a><div class="score">8.0</div></div>
|
||||||
|
<div class="slider-item"><a href="/reviews/6778/tank-war-nation"><img src="album.cover?art=6778" alt="Tank War Nation" /><br /><strong>Tank</strong><br /><em>War Nation</em></a><div class="score">6.5</div></div>
|
||||||
|
<div class="slider-item"><a href="/reviews/6793/satanic-bloodspraying-at-the-mercy-of-satan"><img src="album.cover?art=6793" alt="Satanic Bloodspraying At the Mercy of Satan" /><br /><strong>Satanic Bloodspraying</strong><br /><em>At the Mercy of Satan</em></a><div class="score">8.5</div></div>
|
||||||
|
<div class="slider-item"><a href="/reviews/6791/from-ashes-rise-rejoice-the-end---rage-of-sanity"><img src="album.cover?art=6791" alt="From Ashes Rise Rejoice The End / Rage Of Sanity" /><br /><strong>From Ashes Rise</strong><br /><em>Rejoice The End / Rage Of Sanity</em></a><div class="score">8.0</div></div>
|
||||||
|
<div class="slider-item"><a href="/reviews/6743/ereb-altor-gastrike"><img src="album.cover?art=6743" alt="Ereb Altor Gastrike" /><br /><strong>Ereb Altor</strong><br /><em>Gastrike</em></a><div class="score">8.0</div></div>
|
||||||
|
<div class="slider-item"><a href="/reviews/6794/catheter-southwest-doom-violence"><img src="album.cover?art=6794" alt="Catheter Southwest Doom Violence" /><br /><strong>Catheter</strong><br /><em>Southwest Doom Violence</em></a><div class="score">7.0</div></div>
|
||||||
|
<div class="slider-item"><a href="/reviews/6759/power-theory-an-axe-to-grind"><img src="album.cover?art=6759" alt="Power Theory An Axe to Grind" /><br /><strong>Power Theory</strong><br /><em>An Axe to Grind</em></a><div class="score">6.0</div></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<script type="text/javascript">
|
||||||
|
$(document).ready(function () {
|
||||||
|
$('#latest-reviews-slider').cycle({
|
||||||
|
fx: 'scrollRight',
|
||||||
|
speed: 'fast',
|
||||||
|
timeout: 0,
|
||||||
|
next: '#slider-next-button',
|
||||||
|
prev: '#slider-back-button'
|
||||||
|
});
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div id="homepage-mid-horizontal-zone">
|
||||||
|
<script language="javascript" type="text/javascript" src="http://metalreview.com/bannermgr/abm.aspx?z=1"></script>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<div id="news-feed">
|
||||||
|
<h2>News</h2><div class="news-feed-line"><a href="http://www.bravewords.com/news/190057" target="_blank"><span class="news-link"><strong><span class="new-news">NEW</span> CENTURIAN To Release Contra Rationem Album This Winter</strong></span></a><br /><span class="publish-date">9/12/2012</span></div><br />
|
||||||
|
<div class="news-feed-line"><a href="http://www.bravewords.com/news/190056" target="_blank"><span class="news-link"><strong><span class="new-news">NEW</span> Southwest Terror Fest 2012 - Lineup Changes Announced</strong></span></a><br /><span class="publish-date">9/12/2012</span></div><br />
|
||||||
|
<div class="news-feed-line"><a href="http://www.bravewords.com/news/190055" target="_blank"><span class="news-link"><strong><span class="new-news">NEW</span> ROB ZOMBIE Premiers The Lords Of Salem At TIFF; Q&A Video Posted</strong></span></a><br /><span class="publish-date">9/12/2012</span></div><br />
|
||||||
|
<div class="news-feed-line"><a href="http://www.bravewords.com/news/190054" target="_blank"><span class="news-link"><strong><span class="new-news">NEW</span> THIN LIZZY Keyboardist Darren Wharton's DARE - Calm Before The Storm 2 Album Details Revealed</strong></span></a><br /><span class="publish-date">9/12/2012</span></div><br />
|
||||||
|
<div class="news-feed-line"><a href="http://www.bravewords.com/news/190053" target="_blank"><span class="news-link"><strong><span class="new-news">NEW</span> Japan's LIV MOON To Release Fourth Album; Features Past/Present Members Of EUROPE, ANGRA, HAMMERFALL</strong></span></a><br /><span class="publish-date">9/12/2012</span></div><br />
|
||||||
|
<div class="news-feed-line"><a href="http://www.bravewords.com/news/190052" target="_blank"><span class="news-link"><strong><span class="new-news">NEW</span> SLASH - Sydney Show To Premier This Friday, Free And In HD; Trailer Posted</strong></span></a><br /><span class="publish-date">9/12/2012</span></div><br />
|
||||||
|
<div class="news-feed-line"><a href="http://www.bravewords.com/news/190051" target="_blank"><span class="news-link"><strong><span class="new-news">NEW</span> KHAØS - New Band Featuring Members Of OUTLOUD, TRIBAL, JORN And ELIS To Release New EP In October; Teaser Posted </strong></span></a><br /><span class="publish-date">9/12/2012</span></div><br />
|
||||||
|
<div class="news-feed-line"><a href="http://www.bravewords.com/news/190050" target="_blank"><span class="news-link"><strong><span class="new-news">NEW</span> RECKLESS LOVE Confirm Guests For London Residency Shows In October</strong></span></a><br /><span class="publish-date">9/12/2012</span></div><br />
|
||||||
|
<div class="news-feed-line"><a href="http://www.bravewords.com/news/190049" target="_blank"><span class="news-link"><strong>NASHVILLE PUSSY Add Dates In France, Sweden To European Tour Schedule; Bassist Karen Cuda Sidelined With Back Injury </strong></span></a><br /><span class="publish-date">9/12/2012</span></div><br />
|
||||||
|
<div class="news-feed-line"><a href="http://www.bravewords.com/news/190048" target="_blank"><span class="news-link"><strong>CALIBAN Post Behind-The-Scenes Tour Footage</strong></span></a><br /><span class="publish-date">9/12/2012</span></div><br />
|
||||||
|
<div class="news-feed-line"><a href="http://www.bravewords.com/news/190047" target="_blank"><span class="news-link"><strong>Ex-MERCYFUL FATE Drummer Kim Ruzz Forms New Band METALRUZZ</strong></span></a><br /><span class="publish-date">9/12/2012</span></div><br />
|
||||||
|
<div class="news-feed-line"><a href="http://www.bravewords.com/news/190046" target="_blank"><span class="news-link"><strong>GRAVE Mainman On Endless Procession Of Souls - "These Are The Most ‘Song-Oriented’ Tracks We’ve Done In A Long Time"</strong></span></a><br /><span class="publish-date">9/12/2012</span></div><br />
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<div id="lashes-feed">
|
||||||
|
<h2>Lashes</h2>
|
||||||
|
<div class="lashes-feed-line"><a href="/reviews/6855/katatonia-dead-end-kings#81760"><span class="new-lash">NEW</span> <span class="lashes-link"><strong>Katatonia - Dead End Kings</strong></span></a><br /><span class="publish-date">45 minutes ago by Chaosjunkie</span></div>
|
||||||
|
<div class="lashes-feed-line"><a href="/reviews/6855/katatonia-dead-end-kings#81759"><span class="lashes-link"><strong>Katatonia - Dead End Kings</strong></span></a><br /><span class="publish-date">1 hour ago by Harry Dick Rotten</span></div>
|
||||||
|
<div class="lashes-feed-line"><a href="/reviews/6746/resurgency-false-enlightenment#81758"><span class="lashes-link"><strong>Resurgency - False Enlightenment</strong></span></a><br /><span class="publish-date">3 hours ago by Anonymous</span></div>
|
||||||
|
<div class="lashes-feed-line"><a href="/reviews/4095/witchcraft-the-alchemist#81757"><span class="lashes-link"><strong>Witchcraft - The Alchemist</strong></span></a><br /><span class="publish-date">5 hours ago by Luke_22</span></div>
|
||||||
|
<div class="lashes-feed-line"><a href="/reviews/6855/katatonia-dead-end-kings#81756"><span class="lashes-link"><strong>Katatonia - Dead End Kings</strong></span></a><br /><span class="publish-date">9 hours ago by chaosjunkie</span></div>
|
||||||
|
<div class="lashes-feed-line"><a href="/reviews/6855/katatonia-dead-end-kings#81755"><span class="lashes-link"><strong>Katatonia - Dead End Kings</strong></span></a><br /><span class="publish-date">10 hours ago by Compeller</span></div>
|
||||||
|
<div class="lashes-feed-line"><a href="/reviews/6827/manetheren-time#81754"><span class="lashes-link"><strong>Manetheren - Time</strong></span></a><br /><span class="publish-date">10 hours ago by xpmule</span></div>
|
||||||
|
<div class="lashes-feed-line"><a href="/reviews/6835/ufomammut-oro--opus-alter#81753"><span class="lashes-link"><strong>Ufomammut - Oro: Opus Alter</strong></span></a><br /><span class="publish-date">16 hours ago by Anonymous</span></div>
|
||||||
|
<div class="lashes-feed-line"><a href="/reviews/6835/ufomammut-oro--opus-alter#81752"><span class="lashes-link"><strong>Ufomammut - Oro: Opus Alter</strong></span></a><br /><span class="publish-date">17 hours ago by Harry Dick Rotten</span></div>
|
||||||
|
<div class="lashes-feed-line"><a href="/reviews/6855/katatonia-dead-end-kings#81751"><span class="lashes-link"><strong>Katatonia - Dead End Kings</strong></span></a><br /><span class="publish-date">yesterday by Chaosjunkie</span></div>
|
||||||
|
<div class="lashes-feed-line"><a href="/reviews/6855/katatonia-dead-end-kings#81750"><span class="lashes-link"><strong>Katatonia - Dead End Kings</strong></span></a><br /><span class="publish-date">yesterday by Anonymous</span></div>
|
||||||
|
<div class="lashes-feed-line"><a href="/reviews/6855/katatonia-dead-end-kings#81749"><span class="lashes-link"><strong>Katatonia - Dead End Kings</strong></span></a><br /><span class="publish-date">yesterday by Anonymous</span></div>
|
||||||
|
<div class="lashes-feed-line"><a href="/reviews/6855/katatonia-dead-end-kings#81748"><span class="lashes-link"><strong>Katatonia - Dead End Kings</strong></span></a><br /><span class="publish-date">yesterday by Anonymous</span></div>
|
||||||
|
<div class="lashes-feed-line"><a href="/reviews/6855/katatonia-dead-end-kings#81747"><span class="lashes-link"><strong>Katatonia - Dead End Kings</strong></span></a><br /><span class="publish-date">yesterday by frantic</span></div>
|
||||||
|
<div class="lashes-feed-line"><a href="/reviews/6829/blut-aus-nord-777---cosmosophy#81746"><span class="lashes-link"><strong>Blut Aus Nord - 777 - Cosmosophy</strong></span></a><br /><span class="publish-date">yesterday by Dimensional Bleedthrough</span></div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div id="ft">
|
||||||
|
|
||||||
|
|
||||||
|
<div id="template-footer">
|
||||||
|
<div class="left-column">
|
||||||
|
<ul>
|
||||||
|
<li><a href="/">Home</a></li>
|
||||||
|
<li><a href="/reviews/browse">Reviews</a></li>
|
||||||
|
<li><a href="/tags">Genre Tags</a></li>
|
||||||
|
<li><a href="http://community2.metalreview.com/blogs/editorials/default.aspx">Features</a></li>
|
||||||
|
<li><a href="/artists/browse">Artists</a></li>
|
||||||
|
<li><a href="/reviews/pipeline">Pipeline</a></li>
|
||||||
|
<li><a href="http://community2.metalreview.com/forums">Forums</a></li>
|
||||||
|
<li><a href="/aboutus">About Us</a></li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
<div class="middle-column">
|
||||||
|
<ul>
|
||||||
|
<li><a href="/aboutus/disclaimer">Disclaimer</a></li>
|
||||||
|
<li><a href="/aboutus/privacypolicy">Privacy Policy</a></li>
|
||||||
|
<li><a href="/aboutus/advertising">Advertising</a></li>
|
||||||
|
<li><a href="http://community2.metalreview.com/blogs/eminor/archive/2008/10/27/write-for-metal-review.aspx">Write For Us</a></li>
|
||||||
|
<li><a href="/contactus">Contact Us</a></li>
|
||||||
|
<li><a href="/contactus">Digital Promos</a></li>
|
||||||
|
<li><a href="/contactus">Mailing Address</a></li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
<div class="right-column">
|
||||||
|
<ul>
|
||||||
|
<li><a href="http://feeds.feedburner.com/metalreviews">Reviews RSS Feed</a></li>
|
||||||
|
<li><a href="http://twitter.com/metalreview">Twitter</a></li>
|
||||||
|
<li><a href="http://www.myspace.com/metalreviewdotcom">MySpace</a></li>
|
||||||
|
<li><a href="http://www.last.fm/group/MetalReview.com">Last.fm</a></li>
|
||||||
|
<li><a href="http://www.facebook.com/pages/MetalReviewcom/48371319443">Facebook</a></li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
<div class="square-ad">
|
||||||
|
|
||||||
|
|
||||||
|
<!--JavaScript Tag // Tag for network 5110: Fixion Media // Website: Metalreview // Page: ROS // Placement: ROS-Middle-300 x 250 (1127996) // created at: Oct 19, 2009 6:48:27 PM-->
|
||||||
|
<script type="text/javascript" language="javascript"><!--
|
||||||
|
document.write('<scr' + 'ipt language="javascript1.1" src="http://adserver.adtechus.com/addyn/3.0/5110/1127996/0/170/ADTECH;loc=100;target=_blank;key=key1+key2+key3+key4;grp=[group];misc=' + new Date().getTime() + '"></scri' + 'pt>');
|
||||||
|
//-->
|
||||||
|
</script><noscript><a href="http://adserver.adtechus.com/adlink/3.0/5110/1127996/0/170/ADTECH;loc=300;key=key1+key2+key3+key4;grp=[group]" target="_blank"><img src="http://adserver.adtechus.com/adserv/3.0/5110/1127996/0/170/ADTECH;loc=300;key=key1+key2+key3+key4;grp=[group]" border="0" width="300" height="250"></a></noscript>
|
||||||
|
<!-- End of JavaScript Tag -->
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script type="text/javascript">
|
||||||
|
var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
|
||||||
|
document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script type="text/javascript">
|
||||||
|
var pageTracker = _gat._getTracker("UA-3455310-1");
|
||||||
|
pageTracker._initData();
|
||||||
|
pageTracker._trackPageview();
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<!--JavaScript Tag // Tag for network 5110: Fixion Media // Website: Metalreview // Page: BACKGROUND ADS // Placement: BACKGROUND ADS-Top-1 x 1 (2186116) // created at: Aug 18, 2011 7:20:38 PM-->
|
||||||
|
<script language="javascript"><!--
|
||||||
|
document.write('<scr' + 'ipt language="javascript1.1" src="http://adserver.adtechus.com/addyn/3.0/5110/2186116/0/16/ADTECH;loc=100;target=_blank;key=key1+key2+key3+key4;grp=[group];misc=' + new Date().getTime() + '"></scri' + 'pt>');
|
||||||
|
//-->
|
||||||
|
</script><noscript><a href="http://adserver.adtechus.com/adlink/3.0/5110/2186116/0/16/ADTECH;loc=300;key=key1+key2+key3+key4;grp=[group]" target="_blank"><img src="http://adserver.adtechus.com/adserv/3.0/5110/2186116/0/16/ADTECH;loc=300;key=key1+key2+key3+key4;grp=[group]" border="0" width="1" height="1"></a></noscript>
|
||||||
|
<!-- End of JavaScript Tag -->
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
102
Godeps/_workspace/src/github.com/PuerkitoBio/goquery/testdata/page.html
generated
vendored
Normal file
102
Godeps/_workspace/src/github.com/PuerkitoBio/goquery/testdata/page.html
generated
vendored
Normal file
|
@ -0,0 +1,102 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en" ng-app="app">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
|
||||||
|
<title>
|
||||||
|
Provok.in
|
||||||
|
</title>
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<meta name="description" content="Provok.in - Prove your point. State an affirmation, back it up with evidence, unveil the truth.">
|
||||||
|
<meta name="author" content="Martin Angers">
|
||||||
|
<link href="http://fonts.googleapis.com/css?family=Belgrano" rel="stylesheet" type="text/css">
|
||||||
|
<!--[if lt IE 9]><link href="http://fonts.googleapis.com/css?family=Belgrano" rel="stylesheet" type="text/css"><link href="http://fonts.googleapis.com/css?family=Belgrano:400italic" rel="stylesheet" type="text/css"><link href="http://fonts.googleapis.com/css?family=Belgrano:700" rel="stylesheet" type="text/css"><link href="http://fonts.googleapis.com/css?family=Belgrano:700italic" rel="stylesheet" type="text/css"><![endif]-->
|
||||||
|
<link href="/css/pvk.min.css" rel="stylesheet" type="text/css">
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div class="container-fluid" id="cf1">
|
||||||
|
<div class="row-fluid">
|
||||||
|
<div class="pvk-gutter">
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<div class="pvk-content" id="pc1">
|
||||||
|
<div ng-controller="HeroCtrl" class="hero-unit">
|
||||||
|
<div class="container-fluid" id="cf2">
|
||||||
|
<div class="row-fluid" id="cf2-1">
|
||||||
|
<div class="span12">
|
||||||
|
<h1>
|
||||||
|
<a href="/">Provok<span class="green">.</span><span class="red">i</span>n</a>
|
||||||
|
</h1>
|
||||||
|
<p>
|
||||||
|
Prove your point.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row-fluid" id="cf2-2">
|
||||||
|
<div class="span12 alert alert-error">
|
||||||
|
<strong>Beta Version.</strong> Things may change. Or disappear. Or fail miserably. If it's the latter, <a href="https://github.com/PuerkitoBio/Provok.in-issues" target="_blank" class="link">please file an issue.</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div ng-cloak="" ng-show="isLoggedOut() && !hideLogin" class="row-fluid" id="cf2-3">
|
||||||
|
<a ng-href="{{ROUTES.login}}" class="btn btn-primary">Sign in. Painless.</a> <span>or</span> <a ng-href="{{ROUTES.help}}" class="link">learn more about provok.in.</a>
|
||||||
|
</div>
|
||||||
|
<div ng-cloak="" ng-show="isLoggedIn()" class="row-fluid logged-in-state" id="cf2-4">
|
||||||
|
<span>Welcome,</span> <a ng-href="{{ROUTES.profile}}" class="link">{{getUserName()}}</a> <span>(</span> <a ng-click="doLogout($event)" class="link">logout</a> <span>)</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="pvk-gutter">
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row-fluid">
|
||||||
|
<div class="pvk-gutter">
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<div class="pvk-content" id="pc2">
|
||||||
|
<div class="container-fluid" id="cf3">
|
||||||
|
<div class="row-fluid">
|
||||||
|
<div ng-cloak="" view-on-display="" ng-controller="MsgCtrl" ng-class="{'displayed': blockIsDisplayed}" class="message-box">
|
||||||
|
<div ng-class="{'alert-info': isInfo, 'alert-error': !isInfo, 'displayed': isDisplayed}" class="alert">
|
||||||
|
<a ng-click="hideMessage(true, $event)" class="close">×</a>
|
||||||
|
<h4 class="alert-heading">
|
||||||
|
{{ title }}
|
||||||
|
</h4>
|
||||||
|
<p>
|
||||||
|
{{ message }}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="container-fluid" id="cf4">
|
||||||
|
<div ng-controller="ShareCtrl" ng-hide="isHidden" class="row-fluid center-content"></div>
|
||||||
|
</div>
|
||||||
|
<div ng-view=""></div>
|
||||||
|
</div>
|
||||||
|
<div class="pvk-gutter">
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row-fluid">
|
||||||
|
<div class="pvk-gutter">
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<div class="pvk-content">
|
||||||
|
<div class="footer">
|
||||||
|
<p>
|
||||||
|
<a href="/" class="link">Home</a> <span>|</span> <a href="/about" class="link">About</a> <span>|</span> <a href="/help" class="link">Help</a>
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
<small>© 2012 Martin Angers</small>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="pvk-gutter">
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
24
Godeps/_workspace/src/github.com/PuerkitoBio/goquery/testdata/page2.html
generated
vendored
Normal file
24
Godeps/_workspace/src/github.com/PuerkitoBio/goquery/testdata/page2.html
generated
vendored
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>Tests for siblings</title>
|
||||||
|
</head>
|
||||||
|
<BODY>
|
||||||
|
<div id="main">
|
||||||
|
<div id="n1" class="one even row"></div>
|
||||||
|
<div id="n2" class="two odd row"></div>
|
||||||
|
<div id="n3" class="three even row"></div>
|
||||||
|
<div id="n4" class="four odd row"></div>
|
||||||
|
<div id="n5" class="five even row"></div>
|
||||||
|
<div id="n6" class="six odd row"></div>
|
||||||
|
</div>
|
||||||
|
<div id="foot">
|
||||||
|
<div id="nf1" class="one even row"></div>
|
||||||
|
<div id="nf2" class="two odd row"></div>
|
||||||
|
<div id="nf3" class="three even row"></div>
|
||||||
|
<div id="nf4" class="four odd row"></div>
|
||||||
|
<div id="nf5" class="five even row odder"></div>
|
||||||
|
<div id="nf6" class="six odd row"></div>
|
||||||
|
</div>
|
||||||
|
</BODY>
|
||||||
|
</html>
|
24
Godeps/_workspace/src/github.com/PuerkitoBio/goquery/testdata/page3.html
generated
vendored
Normal file
24
Godeps/_workspace/src/github.com/PuerkitoBio/goquery/testdata/page3.html
generated
vendored
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>Tests for siblings</title>
|
||||||
|
</head>
|
||||||
|
<BODY>
|
||||||
|
<div id="main">
|
||||||
|
<div id="n1" class="one even row">hello</div>
|
||||||
|
<div id="n2" class="two odd row"></div>
|
||||||
|
<div id="n3" class="three even row"></div>
|
||||||
|
<div id="n4" class="four odd row"></div>
|
||||||
|
<div id="n5" class="five even row"></div>
|
||||||
|
<div id="n6" class="six odd row"></div>
|
||||||
|
</div>
|
||||||
|
<div id="foot">
|
||||||
|
<div id="nf1" class="one even row">text</div>
|
||||||
|
<div id="nf2" class="two odd row"></div>
|
||||||
|
<div id="nf3" class="three even row"></div>
|
||||||
|
<div id="nf4" class="four odd row"></div>
|
||||||
|
<div id="nf5" class="five even row odder"></div>
|
||||||
|
<div id="nf6" class="six odd row"></div>
|
||||||
|
</div>
|
||||||
|
</BODY>
|
||||||
|
</html>
|
696
Godeps/_workspace/src/github.com/PuerkitoBio/goquery/traversal.go
generated
vendored
Normal file
696
Godeps/_workspace/src/github.com/PuerkitoBio/goquery/traversal.go
generated
vendored
Normal file
|
@ -0,0 +1,696 @@
|
||||||
|
package goquery
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/andybalholm/cascadia"
|
||||||
|
"golang.org/x/net/html"
|
||||||
|
)
|
||||||
|
|
||||||
|
type siblingType int
|
||||||
|
|
||||||
|
// Sibling type, used internally when iterating over children at the same
|
||||||
|
// level (siblings) to specify which nodes are requested.
|
||||||
|
const (
|
||||||
|
siblingPrevUntil siblingType = iota - 3
|
||||||
|
siblingPrevAll
|
||||||
|
siblingPrev
|
||||||
|
siblingAll
|
||||||
|
siblingNext
|
||||||
|
siblingNextAll
|
||||||
|
siblingNextUntil
|
||||||
|
siblingAllIncludingNonElements
|
||||||
|
)
|
||||||
|
|
||||||
|
// Find gets the descendants of each element in the current set of matched
|
||||||
|
// elements, filtered by a selector. It returns a new Selection object
|
||||||
|
// containing these matched elements.
|
||||||
|
func (s *Selection) Find(selector string) *Selection {
|
||||||
|
return pushStack(s, findWithMatcher(s.Nodes, cascadia.MustCompile(selector)))
|
||||||
|
}
|
||||||
|
|
||||||
|
// FindMatcher gets the descendants of each element in the current set of matched
|
||||||
|
// elements, filtered by the matcher. It returns a new Selection object
|
||||||
|
// containing these matched elements.
|
||||||
|
func (s *Selection) FindMatcher(m Matcher) *Selection {
|
||||||
|
return pushStack(s, findWithMatcher(s.Nodes, m))
|
||||||
|
}
|
||||||
|
|
||||||
|
// FindSelection gets the descendants of each element in the current
|
||||||
|
// Selection, filtered by a Selection. It returns a new Selection object
|
||||||
|
// containing these matched elements.
|
||||||
|
func (s *Selection) FindSelection(sel *Selection) *Selection {
|
||||||
|
if sel == nil {
|
||||||
|
return pushStack(s, nil)
|
||||||
|
}
|
||||||
|
return s.FindNodes(sel.Nodes...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// FindNodes gets the descendants of each element in the current
|
||||||
|
// Selection, filtered by some nodes. It returns a new Selection object
|
||||||
|
// containing these matched elements.
|
||||||
|
func (s *Selection) FindNodes(nodes ...*html.Node) *Selection {
|
||||||
|
return pushStack(s, mapNodes(nodes, func(i int, n *html.Node) []*html.Node {
|
||||||
|
if sliceContains(s.Nodes, n) {
|
||||||
|
return []*html.Node{n}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Contents gets the children of each element in the Selection,
|
||||||
|
// including text and comment nodes. It returns a new Selection object
|
||||||
|
// containing these elements.
|
||||||
|
func (s *Selection) Contents() *Selection {
|
||||||
|
return pushStack(s, getChildrenNodes(s.Nodes, siblingAllIncludingNonElements))
|
||||||
|
}
|
||||||
|
|
||||||
|
// ContentsFiltered gets the children of each element in the Selection,
|
||||||
|
// filtered by the specified selector. It returns a new Selection
|
||||||
|
// object containing these elements. Since selectors only act on Element nodes,
|
||||||
|
// this function is an alias to ChildrenFiltered unless the selector is empty,
|
||||||
|
// in which case it is an alias to Contents.
|
||||||
|
func (s *Selection) ContentsFiltered(selector string) *Selection {
|
||||||
|
if selector != "" {
|
||||||
|
return s.ChildrenFiltered(selector)
|
||||||
|
}
|
||||||
|
return s.Contents()
|
||||||
|
}
|
||||||
|
|
||||||
|
// ContentsMatcher gets the children of each element in the Selection,
|
||||||
|
// filtered by the specified matcher. It returns a new Selection
|
||||||
|
// object containing these elements. Since matchers only act on Element nodes,
|
||||||
|
// this function is an alias to ChildrenMatcher.
|
||||||
|
func (s *Selection) ContentsMatcher(m Matcher) *Selection {
|
||||||
|
return s.ChildrenMatcher(m)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Children gets the child elements of each element in the Selection.
|
||||||
|
// It returns a new Selection object containing these elements.
|
||||||
|
func (s *Selection) Children() *Selection {
|
||||||
|
return pushStack(s, getChildrenNodes(s.Nodes, siblingAll))
|
||||||
|
}
|
||||||
|
|
||||||
|
// ChildrenFiltered gets the child elements of each element in the Selection,
|
||||||
|
// filtered by the specified selector. It returns a new
|
||||||
|
// Selection object containing these elements.
|
||||||
|
func (s *Selection) ChildrenFiltered(selector string) *Selection {
|
||||||
|
return filterAndPush(s, getChildrenNodes(s.Nodes, siblingAll), cascadia.MustCompile(selector))
|
||||||
|
}
|
||||||
|
|
||||||
|
// ChildrenMatcher gets the child elements of each element in the Selection,
|
||||||
|
// filtered by the specified matcher. It returns a new
|
||||||
|
// Selection object containing these elements.
|
||||||
|
func (s *Selection) ChildrenMatcher(m Matcher) *Selection {
|
||||||
|
return filterAndPush(s, getChildrenNodes(s.Nodes, siblingAll), m)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parent gets the parent of each element in the Selection. It returns a
|
||||||
|
// new Selection object containing the matched elements.
|
||||||
|
func (s *Selection) Parent() *Selection {
|
||||||
|
return pushStack(s, getParentNodes(s.Nodes))
|
||||||
|
}
|
||||||
|
|
||||||
|
// ParentFiltered gets the parent of each element in the Selection filtered by a
|
||||||
|
// selector. It returns a new Selection object containing the matched elements.
|
||||||
|
func (s *Selection) ParentFiltered(selector string) *Selection {
|
||||||
|
return filterAndPush(s, getParentNodes(s.Nodes), cascadia.MustCompile(selector))
|
||||||
|
}
|
||||||
|
|
||||||
|
// ParentMatcher gets the parent of each element in the Selection filtered by a
|
||||||
|
// matcher. It returns a new Selection object containing the matched elements.
|
||||||
|
func (s *Selection) ParentMatcher(m Matcher) *Selection {
|
||||||
|
return filterAndPush(s, getParentNodes(s.Nodes), m)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Closest gets the first element that matches the selector by testing the
|
||||||
|
// element itself and traversing up through its ancestors in the DOM tree.
|
||||||
|
func (s *Selection) Closest(selector string) *Selection {
|
||||||
|
cs := cascadia.MustCompile(selector)
|
||||||
|
return s.ClosestMatcher(cs)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ClosestMatcher gets the first element that matches the matcher by testing the
|
||||||
|
// element itself and traversing up through its ancestors in the DOM tree.
|
||||||
|
func (s *Selection) ClosestMatcher(m Matcher) *Selection {
|
||||||
|
return pushStack(s, mapNodes(s.Nodes, func(i int, n *html.Node) []*html.Node {
|
||||||
|
// For each node in the selection, test the node itself, then each parent
|
||||||
|
// until a match is found.
|
||||||
|
for ; n != nil; n = n.Parent {
|
||||||
|
if m.Match(n) {
|
||||||
|
return []*html.Node{n}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
|
||||||
|
// ClosestNodes gets the first element that matches one of the nodes by testing the
|
||||||
|
// element itself and traversing up through its ancestors in the DOM tree.
|
||||||
|
func (s *Selection) ClosestNodes(nodes ...*html.Node) *Selection {
|
||||||
|
return pushStack(s, mapNodes(s.Nodes, func(i int, n *html.Node) []*html.Node {
|
||||||
|
// For each node in the selection, test the node itself, then each parent
|
||||||
|
// until a match is found.
|
||||||
|
for ; n != nil; n = n.Parent {
|
||||||
|
if isInSlice(nodes, n) {
|
||||||
|
return []*html.Node{n}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
|
||||||
|
// ClosestSelection gets the first element that matches one of the nodes in the
|
||||||
|
// Selection by testing the element itself and traversing up through its ancestors
|
||||||
|
// in the DOM tree.
|
||||||
|
func (s *Selection) ClosestSelection(sel *Selection) *Selection {
|
||||||
|
if sel == nil {
|
||||||
|
return pushStack(s, nil)
|
||||||
|
}
|
||||||
|
return s.ClosestNodes(sel.Nodes...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parents gets the ancestors of each element in the current Selection. It
|
||||||
|
// returns a new Selection object with the matched elements.
|
||||||
|
func (s *Selection) Parents() *Selection {
|
||||||
|
return pushStack(s, getParentsNodes(s.Nodes, nil, nil))
|
||||||
|
}
|
||||||
|
|
||||||
|
// ParentsFiltered gets the ancestors of each element in the current
|
||||||
|
// Selection. It returns a new Selection object with the matched elements.
|
||||||
|
func (s *Selection) ParentsFiltered(selector string) *Selection {
|
||||||
|
return filterAndPush(s, getParentsNodes(s.Nodes, nil, nil), cascadia.MustCompile(selector))
|
||||||
|
}
|
||||||
|
|
||||||
|
// ParentsMatcher gets the ancestors of each element in the current
|
||||||
|
// Selection. It returns a new Selection object with the matched elements.
|
||||||
|
func (s *Selection) ParentsMatcher(m Matcher) *Selection {
|
||||||
|
return filterAndPush(s, getParentsNodes(s.Nodes, nil, nil), m)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ParentsUntil gets the ancestors of each element in the Selection, up to but
|
||||||
|
// not including the element matched by the selector. It returns a new Selection
|
||||||
|
// object containing the matched elements.
|
||||||
|
func (s *Selection) ParentsUntil(selector string) *Selection {
|
||||||
|
return pushStack(s, getParentsNodes(s.Nodes, cascadia.MustCompile(selector), nil))
|
||||||
|
}
|
||||||
|
|
||||||
|
// ParentsUntilMatcher gets the ancestors of each element in the Selection, up to but
|
||||||
|
// not including the element matched by the matcher. It returns a new Selection
|
||||||
|
// object containing the matched elements.
|
||||||
|
func (s *Selection) ParentsUntilMatcher(m Matcher) *Selection {
|
||||||
|
return pushStack(s, getParentsNodes(s.Nodes, m, nil))
|
||||||
|
}
|
||||||
|
|
||||||
|
// ParentsUntilSelection gets the ancestors of each element in the Selection,
|
||||||
|
// up to but not including the elements in the specified Selection. It returns a
|
||||||
|
// new Selection object containing the matched elements.
|
||||||
|
func (s *Selection) ParentsUntilSelection(sel *Selection) *Selection {
|
||||||
|
if sel == nil {
|
||||||
|
return s.Parents()
|
||||||
|
}
|
||||||
|
return s.ParentsUntilNodes(sel.Nodes...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ParentsUntilNodes gets the ancestors of each element in the Selection,
|
||||||
|
// up to but not including the specified nodes. It returns a
|
||||||
|
// new Selection object containing the matched elements.
|
||||||
|
func (s *Selection) ParentsUntilNodes(nodes ...*html.Node) *Selection {
|
||||||
|
return pushStack(s, getParentsNodes(s.Nodes, nil, nodes))
|
||||||
|
}
|
||||||
|
|
||||||
|
// ParentsFilteredUntil is like ParentsUntil, with the option to filter the
|
||||||
|
// results based on a selector string. It returns a new Selection
|
||||||
|
// object containing the matched elements.
|
||||||
|
func (s *Selection) ParentsFilteredUntil(filterSelector, untilSelector string) *Selection {
|
||||||
|
return filterAndPush(s, getParentsNodes(s.Nodes, cascadia.MustCompile(untilSelector), nil), cascadia.MustCompile(filterSelector))
|
||||||
|
}
|
||||||
|
|
||||||
|
// ParentsFilteredUntilMatcher is like ParentsUntilMatcher, with the option to filter the
|
||||||
|
// results based on a matcher. It returns a new Selection object containing the matched elements.
|
||||||
|
func (s *Selection) ParentsFilteredUntilMatcher(filter, until Matcher) *Selection {
|
||||||
|
return filterAndPush(s, getParentsNodes(s.Nodes, until, nil), filter)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ParentsFilteredUntilSelection is like ParentsUntilSelection, with the
|
||||||
|
// option to filter the results based on a selector string. It returns a new
|
||||||
|
// Selection object containing the matched elements.
|
||||||
|
func (s *Selection) ParentsFilteredUntilSelection(filterSelector string, sel *Selection) *Selection {
|
||||||
|
return s.ParentsMatcherUntilSelection(cascadia.MustCompile(filterSelector), sel)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ParentsMatcherUntilSelection is like ParentsUntilSelection, with the
|
||||||
|
// option to filter the results based on a matcher. It returns a new
|
||||||
|
// Selection object containing the matched elements.
|
||||||
|
func (s *Selection) ParentsMatcherUntilSelection(filter Matcher, sel *Selection) *Selection {
|
||||||
|
if sel == nil {
|
||||||
|
return s.ParentsMatcher(filter)
|
||||||
|
}
|
||||||
|
return s.ParentsMatcherUntilNodes(filter, sel.Nodes...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ParentsFilteredUntilNodes is like ParentsUntilNodes, with the
|
||||||
|
// option to filter the results based on a selector string. It returns a new
|
||||||
|
// Selection object containing the matched elements.
|
||||||
|
func (s *Selection) ParentsFilteredUntilNodes(filterSelector string, nodes ...*html.Node) *Selection {
|
||||||
|
return filterAndPush(s, getParentsNodes(s.Nodes, nil, nodes), cascadia.MustCompile(filterSelector))
|
||||||
|
}
|
||||||
|
|
||||||
|
// ParentsMatcherUntilNodes is like ParentsUntilNodes, with the
|
||||||
|
// option to filter the results based on a matcher. It returns a new
|
||||||
|
// Selection object containing the matched elements.
|
||||||
|
func (s *Selection) ParentsMatcherUntilNodes(filter Matcher, nodes ...*html.Node) *Selection {
|
||||||
|
return filterAndPush(s, getParentsNodes(s.Nodes, nil, nodes), filter)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Siblings gets the siblings of each element in the Selection. It returns
|
||||||
|
// a new Selection object containing the matched elements.
|
||||||
|
func (s *Selection) Siblings() *Selection {
|
||||||
|
return pushStack(s, getSiblingNodes(s.Nodes, siblingAll, nil, nil))
|
||||||
|
}
|
||||||
|
|
||||||
|
// SiblingsFiltered gets the siblings of each element in the Selection
|
||||||
|
// filtered by a selector. It returns a new Selection object containing the
|
||||||
|
// matched elements.
|
||||||
|
func (s *Selection) SiblingsFiltered(selector string) *Selection {
|
||||||
|
return filterAndPush(s, getSiblingNodes(s.Nodes, siblingAll, nil, nil), cascadia.MustCompile(selector))
|
||||||
|
}
|
||||||
|
|
||||||
|
// SiblingsMatcher gets the siblings of each element in the Selection
|
||||||
|
// filtered by a matcher. It returns a new Selection object containing the
|
||||||
|
// matched elements.
|
||||||
|
func (s *Selection) SiblingsMatcher(m Matcher) *Selection {
|
||||||
|
return filterAndPush(s, getSiblingNodes(s.Nodes, siblingAll, nil, nil), m)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Next gets the immediately following sibling of each element in the
|
||||||
|
// Selection. It returns a new Selection object containing the matched elements.
|
||||||
|
func (s *Selection) Next() *Selection {
|
||||||
|
return pushStack(s, getSiblingNodes(s.Nodes, siblingNext, nil, nil))
|
||||||
|
}
|
||||||
|
|
||||||
|
// NextFiltered gets the immediately following sibling of each element in the
|
||||||
|
// Selection filtered by a selector. It returns a new Selection object
|
||||||
|
// containing the matched elements.
|
||||||
|
func (s *Selection) NextFiltered(selector string) *Selection {
|
||||||
|
return filterAndPush(s, getSiblingNodes(s.Nodes, siblingNext, nil, nil), cascadia.MustCompile(selector))
|
||||||
|
}
|
||||||
|
|
||||||
|
// NextMatcher gets the immediately following sibling of each element in the
|
||||||
|
// Selection filtered by a matcher. It returns a new Selection object
|
||||||
|
// containing the matched elements.
|
||||||
|
func (s *Selection) NextMatcher(m Matcher) *Selection {
|
||||||
|
return filterAndPush(s, getSiblingNodes(s.Nodes, siblingNext, nil, nil), m)
|
||||||
|
}
|
||||||
|
|
||||||
|
// NextAll gets all the following siblings of each element in the
|
||||||
|
// Selection. It returns a new Selection object containing the matched elements.
|
||||||
|
func (s *Selection) NextAll() *Selection {
|
||||||
|
return pushStack(s, getSiblingNodes(s.Nodes, siblingNextAll, nil, nil))
|
||||||
|
}
|
||||||
|
|
||||||
|
// NextAllFiltered gets all the following siblings of each element in the
|
||||||
|
// Selection filtered by a selector. It returns a new Selection object
|
||||||
|
// containing the matched elements.
|
||||||
|
func (s *Selection) NextAllFiltered(selector string) *Selection {
|
||||||
|
return filterAndPush(s, getSiblingNodes(s.Nodes, siblingNextAll, nil, nil), cascadia.MustCompile(selector))
|
||||||
|
}
|
||||||
|
|
||||||
|
// NextAllMatcher gets all the following siblings of each element in the
|
||||||
|
// Selection filtered by a matcher. It returns a new Selection object
|
||||||
|
// containing the matched elements.
|
||||||
|
func (s *Selection) NextAllMatcher(m Matcher) *Selection {
|
||||||
|
return filterAndPush(s, getSiblingNodes(s.Nodes, siblingNextAll, nil, nil), m)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Prev gets the immediately preceding sibling of each element in the
|
||||||
|
// Selection. It returns a new Selection object containing the matched elements.
|
||||||
|
func (s *Selection) Prev() *Selection {
|
||||||
|
return pushStack(s, getSiblingNodes(s.Nodes, siblingPrev, nil, nil))
|
||||||
|
}
|
||||||
|
|
||||||
|
// PrevFiltered gets the immediately preceding sibling of each element in the
|
||||||
|
// Selection filtered by a selector. It returns a new Selection object
|
||||||
|
// containing the matched elements.
|
||||||
|
func (s *Selection) PrevFiltered(selector string) *Selection {
|
||||||
|
return filterAndPush(s, getSiblingNodes(s.Nodes, siblingPrev, nil, nil), cascadia.MustCompile(selector))
|
||||||
|
}
|
||||||
|
|
||||||
|
// PrevMatcher gets the immediately preceding sibling of each element in the
|
||||||
|
// Selection filtered by a matcher. It returns a new Selection object
|
||||||
|
// containing the matched elements.
|
||||||
|
func (s *Selection) PrevMatcher(m Matcher) *Selection {
|
||||||
|
return filterAndPush(s, getSiblingNodes(s.Nodes, siblingPrev, nil, nil), m)
|
||||||
|
}
|
||||||
|
|
||||||
|
// PrevAll gets all the preceding siblings of each element in the
|
||||||
|
// Selection. It returns a new Selection object containing the matched elements.
|
||||||
|
func (s *Selection) PrevAll() *Selection {
|
||||||
|
return pushStack(s, getSiblingNodes(s.Nodes, siblingPrevAll, nil, nil))
|
||||||
|
}
|
||||||
|
|
||||||
|
// PrevAllFiltered gets all the preceding siblings of each element in the
|
||||||
|
// Selection filtered by a selector. It returns a new Selection object
|
||||||
|
// containing the matched elements.
|
||||||
|
func (s *Selection) PrevAllFiltered(selector string) *Selection {
|
||||||
|
return filterAndPush(s, getSiblingNodes(s.Nodes, siblingPrevAll, nil, nil), cascadia.MustCompile(selector))
|
||||||
|
}
|
||||||
|
|
||||||
|
// PrevAllMatcher gets all the preceding siblings of each element in the
|
||||||
|
// Selection filtered by a matcher. It returns a new Selection object
|
||||||
|
// containing the matched elements.
|
||||||
|
func (s *Selection) PrevAllMatcher(m Matcher) *Selection {
|
||||||
|
return filterAndPush(s, getSiblingNodes(s.Nodes, siblingPrevAll, nil, nil), m)
|
||||||
|
}
|
||||||
|
|
||||||
|
// NextUntil gets all following siblings of each element up to but not
|
||||||
|
// including the element matched by the selector. It returns a new Selection
|
||||||
|
// object containing the matched elements.
|
||||||
|
func (s *Selection) NextUntil(selector string) *Selection {
|
||||||
|
return pushStack(s, getSiblingNodes(s.Nodes, siblingNextUntil,
|
||||||
|
cascadia.MustCompile(selector), nil))
|
||||||
|
}
|
||||||
|
|
||||||
|
// NextUntilMatcher gets all following siblings of each element up to but not
|
||||||
|
// including the element matched by the matcher. It returns a new Selection
|
||||||
|
// object containing the matched elements.
|
||||||
|
func (s *Selection) NextUntilMatcher(m Matcher) *Selection {
|
||||||
|
return pushStack(s, getSiblingNodes(s.Nodes, siblingNextUntil,
|
||||||
|
m, nil))
|
||||||
|
}
|
||||||
|
|
||||||
|
// NextUntilSelection gets all following siblings of each element up to but not
|
||||||
|
// including the element matched by the Selection. It returns a new Selection
|
||||||
|
// object containing the matched elements.
|
||||||
|
func (s *Selection) NextUntilSelection(sel *Selection) *Selection {
|
||||||
|
if sel == nil {
|
||||||
|
return s.NextAll()
|
||||||
|
}
|
||||||
|
return s.NextUntilNodes(sel.Nodes...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// NextUntilNodes gets all following siblings of each element up to but not
|
||||||
|
// including the element matched by the nodes. It returns a new Selection
|
||||||
|
// object containing the matched elements.
|
||||||
|
func (s *Selection) NextUntilNodes(nodes ...*html.Node) *Selection {
|
||||||
|
return pushStack(s, getSiblingNodes(s.Nodes, siblingNextUntil,
|
||||||
|
nil, nodes))
|
||||||
|
}
|
||||||
|
|
||||||
|
// PrevUntil gets all preceding siblings of each element up to but not
|
||||||
|
// including the element matched by the selector. It returns a new Selection
|
||||||
|
// object containing the matched elements.
|
||||||
|
func (s *Selection) PrevUntil(selector string) *Selection {
|
||||||
|
return pushStack(s, getSiblingNodes(s.Nodes, siblingPrevUntil,
|
||||||
|
cascadia.MustCompile(selector), nil))
|
||||||
|
}
|
||||||
|
|
||||||
|
// PrevUntilMatcher gets all preceding siblings of each element up to but not
|
||||||
|
// including the element matched by the matcher. It returns a new Selection
|
||||||
|
// object containing the matched elements.
|
||||||
|
func (s *Selection) PrevUntilMatcher(m Matcher) *Selection {
|
||||||
|
return pushStack(s, getSiblingNodes(s.Nodes, siblingPrevUntil,
|
||||||
|
m, nil))
|
||||||
|
}
|
||||||
|
|
||||||
|
// PrevUntilSelection gets all preceding siblings of each element up to but not
|
||||||
|
// including the element matched by the Selection. It returns a new Selection
|
||||||
|
// object containing the matched elements.
|
||||||
|
func (s *Selection) PrevUntilSelection(sel *Selection) *Selection {
|
||||||
|
if sel == nil {
|
||||||
|
return s.PrevAll()
|
||||||
|
}
|
||||||
|
return s.PrevUntilNodes(sel.Nodes...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// PrevUntilNodes gets all preceding siblings of each element up to but not
|
||||||
|
// including the element matched by the nodes. It returns a new Selection
|
||||||
|
// object containing the matched elements.
|
||||||
|
func (s *Selection) PrevUntilNodes(nodes ...*html.Node) *Selection {
|
||||||
|
return pushStack(s, getSiblingNodes(s.Nodes, siblingPrevUntil,
|
||||||
|
nil, nodes))
|
||||||
|
}
|
||||||
|
|
||||||
|
// NextFilteredUntil is like NextUntil, with the option to filter
|
||||||
|
// the results based on a selector string.
|
||||||
|
// It returns a new Selection object containing the matched elements.
|
||||||
|
func (s *Selection) NextFilteredUntil(filterSelector, untilSelector string) *Selection {
|
||||||
|
return filterAndPush(s, getSiblingNodes(s.Nodes, siblingNextUntil,
|
||||||
|
cascadia.MustCompile(untilSelector), nil), cascadia.MustCompile(filterSelector))
|
||||||
|
}
|
||||||
|
|
||||||
|
// NextFilteredUntilMatcher is like NextUntilMatcher, with the option to filter
|
||||||
|
// the results based on a matcher.
|
||||||
|
// It returns a new Selection object containing the matched elements.
|
||||||
|
func (s *Selection) NextFilteredUntilMatcher(filter, until Matcher) *Selection {
|
||||||
|
return filterAndPush(s, getSiblingNodes(s.Nodes, siblingNextUntil,
|
||||||
|
until, nil), filter)
|
||||||
|
}
|
||||||
|
|
||||||
|
// NextFilteredUntilSelection is like NextUntilSelection, with the
|
||||||
|
// option to filter the results based on a selector string. It returns a new
|
||||||
|
// Selection object containing the matched elements.
|
||||||
|
func (s *Selection) NextFilteredUntilSelection(filterSelector string, sel *Selection) *Selection {
|
||||||
|
return s.NextMatcherUntilSelection(cascadia.MustCompile(filterSelector), sel)
|
||||||
|
}
|
||||||
|
|
||||||
|
// NextMatcherUntilSelection is like NextUntilSelection, with the
|
||||||
|
// option to filter the results based on a matcher. It returns a new
|
||||||
|
// Selection object containing the matched elements.
|
||||||
|
func (s *Selection) NextMatcherUntilSelection(filter Matcher, sel *Selection) *Selection {
|
||||||
|
if sel == nil {
|
||||||
|
return s.NextMatcher(filter)
|
||||||
|
}
|
||||||
|
return s.NextMatcherUntilNodes(filter, sel.Nodes...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// NextFilteredUntilNodes is like NextUntilNodes, with the
|
||||||
|
// option to filter the results based on a selector string. It returns a new
|
||||||
|
// Selection object containing the matched elements.
|
||||||
|
func (s *Selection) NextFilteredUntilNodes(filterSelector string, nodes ...*html.Node) *Selection {
|
||||||
|
return filterAndPush(s, getSiblingNodes(s.Nodes, siblingNextUntil,
|
||||||
|
nil, nodes), cascadia.MustCompile(filterSelector))
|
||||||
|
}
|
||||||
|
|
||||||
|
// NextMatcherUntilNodes is like NextUntilNodes, with the
|
||||||
|
// option to filter the results based on a matcher. It returns a new
|
||||||
|
// Selection object containing the matched elements.
|
||||||
|
func (s *Selection) NextMatcherUntilNodes(filter Matcher, nodes ...*html.Node) *Selection {
|
||||||
|
return filterAndPush(s, getSiblingNodes(s.Nodes, siblingNextUntil,
|
||||||
|
nil, nodes), filter)
|
||||||
|
}
|
||||||
|
|
||||||
|
// PrevFilteredUntil is like PrevUntil, with the option to filter
|
||||||
|
// the results based on a selector string.
|
||||||
|
// It returns a new Selection object containing the matched elements.
|
||||||
|
func (s *Selection) PrevFilteredUntil(filterSelector, untilSelector string) *Selection {
|
||||||
|
return filterAndPush(s, getSiblingNodes(s.Nodes, siblingPrevUntil,
|
||||||
|
cascadia.MustCompile(untilSelector), nil), cascadia.MustCompile(filterSelector))
|
||||||
|
}
|
||||||
|
|
||||||
|
// PrevFilteredUntilMatcher is like PrevUntilMatcher, with the option to filter
|
||||||
|
// the results based on a matcher.
|
||||||
|
// It returns a new Selection object containing the matched elements.
|
||||||
|
func (s *Selection) PrevFilteredUntilMatcher(filter, until Matcher) *Selection {
|
||||||
|
return filterAndPush(s, getSiblingNodes(s.Nodes, siblingPrevUntil,
|
||||||
|
until, nil), filter)
|
||||||
|
}
|
||||||
|
|
||||||
|
// PrevFilteredUntilSelection is like PrevUntilSelection, with the
|
||||||
|
// option to filter the results based on a selector string. It returns a new
|
||||||
|
// Selection object containing the matched elements.
|
||||||
|
func (s *Selection) PrevFilteredUntilSelection(filterSelector string, sel *Selection) *Selection {
|
||||||
|
return s.PrevMatcherUntilSelection(cascadia.MustCompile(filterSelector), sel)
|
||||||
|
}
|
||||||
|
|
||||||
|
// PrevMatcherUntilSelection is like PrevUntilSelection, with the
|
||||||
|
// option to filter the results based on a matcher. It returns a new
|
||||||
|
// Selection object containing the matched elements.
|
||||||
|
func (s *Selection) PrevMatcherUntilSelection(filter Matcher, sel *Selection) *Selection {
|
||||||
|
if sel == nil {
|
||||||
|
return s.PrevMatcher(filter)
|
||||||
|
}
|
||||||
|
return s.PrevMatcherUntilNodes(filter, sel.Nodes...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// PrevFilteredUntilNodes is like PrevUntilNodes, with the
|
||||||
|
// option to filter the results based on a selector string. It returns a new
|
||||||
|
// Selection object containing the matched elements.
|
||||||
|
func (s *Selection) PrevFilteredUntilNodes(filterSelector string, nodes ...*html.Node) *Selection {
|
||||||
|
return filterAndPush(s, getSiblingNodes(s.Nodes, siblingPrevUntil,
|
||||||
|
nil, nodes), cascadia.MustCompile(filterSelector))
|
||||||
|
}
|
||||||
|
|
||||||
|
// PrevMatcherUntilNodes is like PrevUntilNodes, with the
|
||||||
|
// option to filter the results based on a matcher. It returns a new
|
||||||
|
// Selection object containing the matched elements.
|
||||||
|
func (s *Selection) PrevMatcherUntilNodes(filter Matcher, nodes ...*html.Node) *Selection {
|
||||||
|
return filterAndPush(s, getSiblingNodes(s.Nodes, siblingPrevUntil,
|
||||||
|
nil, nodes), filter)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Filter and push filters the nodes based on a matcher, and pushes the results
|
||||||
|
// on the stack, with the srcSel as previous selection.
|
||||||
|
func filterAndPush(srcSel *Selection, nodes []*html.Node, m Matcher) *Selection {
|
||||||
|
// Create a temporary Selection with the specified nodes to filter using winnow
|
||||||
|
sel := &Selection{nodes, srcSel.document, nil}
|
||||||
|
// Filter based on matcher and push on stack
|
||||||
|
return pushStack(srcSel, winnow(sel, m, true))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Internal implementation of Find that return raw nodes.
|
||||||
|
func findWithMatcher(nodes []*html.Node, m Matcher) []*html.Node {
|
||||||
|
// Map nodes to find the matches within the children of each node
|
||||||
|
return mapNodes(nodes, func(i int, n *html.Node) (result []*html.Node) {
|
||||||
|
// Go down one level, becausejQuery's Find selects only within descendants
|
||||||
|
for c := n.FirstChild; c != nil; c = c.NextSibling {
|
||||||
|
if c.Type == html.ElementNode {
|
||||||
|
result = append(result, m.MatchAll(c)...)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// Internal implementation to get all parent nodes, stopping at the specified
|
||||||
|
// node (or nil if no stop).
|
||||||
|
func getParentsNodes(nodes []*html.Node, stopm Matcher, stopNodes []*html.Node) []*html.Node {
|
||||||
|
return mapNodes(nodes, func(i int, n *html.Node) (result []*html.Node) {
|
||||||
|
for p := n.Parent; p != nil; p = p.Parent {
|
||||||
|
sel := newSingleSelection(p, nil)
|
||||||
|
if stopm != nil {
|
||||||
|
if sel.IsMatcher(stopm) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
} else if len(stopNodes) > 0 {
|
||||||
|
if sel.IsNodes(stopNodes...) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if p.Type == html.ElementNode {
|
||||||
|
result = append(result, p)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// Internal implementation of sibling nodes that return a raw slice of matches.
|
||||||
|
func getSiblingNodes(nodes []*html.Node, st siblingType, untilm Matcher, untilNodes []*html.Node) []*html.Node {
|
||||||
|
var f func(*html.Node) bool
|
||||||
|
|
||||||
|
// If the requested siblings are ...Until, create the test function to
|
||||||
|
// determine if the until condition is reached (returns true if it is)
|
||||||
|
if st == siblingNextUntil || st == siblingPrevUntil {
|
||||||
|
f = func(n *html.Node) bool {
|
||||||
|
if untilm != nil {
|
||||||
|
// Matcher-based condition
|
||||||
|
sel := newSingleSelection(n, nil)
|
||||||
|
return sel.IsMatcher(untilm)
|
||||||
|
} else if len(untilNodes) > 0 {
|
||||||
|
// Nodes-based condition
|
||||||
|
sel := newSingleSelection(n, nil)
|
||||||
|
return sel.IsNodes(untilNodes...)
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return mapNodes(nodes, func(i int, n *html.Node) []*html.Node {
|
||||||
|
return getChildrenWithSiblingType(n.Parent, st, n, f)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// Gets the children nodes of each node in the specified slice of nodes,
|
||||||
|
// based on the sibling type request.
|
||||||
|
func getChildrenNodes(nodes []*html.Node, st siblingType) []*html.Node {
|
||||||
|
return mapNodes(nodes, func(i int, n *html.Node) []*html.Node {
|
||||||
|
return getChildrenWithSiblingType(n, st, nil, nil)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// Gets the children of the specified parent, based on the requested sibling
|
||||||
|
// type, skipping a specified node if required.
|
||||||
|
func getChildrenWithSiblingType(parent *html.Node, st siblingType, skipNode *html.Node,
|
||||||
|
untilFunc func(*html.Node) bool) (result []*html.Node) {
|
||||||
|
|
||||||
|
// Create the iterator function
|
||||||
|
var iter = func(cur *html.Node) (ret *html.Node) {
|
||||||
|
// Based on the sibling type requested, iterate the right way
|
||||||
|
for {
|
||||||
|
switch st {
|
||||||
|
case siblingAll, siblingAllIncludingNonElements:
|
||||||
|
if cur == nil {
|
||||||
|
// First iteration, start with first child of parent
|
||||||
|
// Skip node if required
|
||||||
|
if ret = parent.FirstChild; ret == skipNode && skipNode != nil {
|
||||||
|
ret = skipNode.NextSibling
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Skip node if required
|
||||||
|
if ret = cur.NextSibling; ret == skipNode && skipNode != nil {
|
||||||
|
ret = skipNode.NextSibling
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case siblingPrev, siblingPrevAll, siblingPrevUntil:
|
||||||
|
if cur == nil {
|
||||||
|
// Start with previous sibling of the skip node
|
||||||
|
ret = skipNode.PrevSibling
|
||||||
|
} else {
|
||||||
|
ret = cur.PrevSibling
|
||||||
|
}
|
||||||
|
case siblingNext, siblingNextAll, siblingNextUntil:
|
||||||
|
if cur == nil {
|
||||||
|
// Start with next sibling of the skip node
|
||||||
|
ret = skipNode.NextSibling
|
||||||
|
} else {
|
||||||
|
ret = cur.NextSibling
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
panic("Invalid sibling type.")
|
||||||
|
}
|
||||||
|
if ret == nil || ret.Type == html.ElementNode || st == siblingAllIncludingNonElements {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// Not a valid node, try again from this one
|
||||||
|
cur = ret
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for c := iter(nil); c != nil; c = iter(c) {
|
||||||
|
// If this is an ...Until case, test before append (returns true
|
||||||
|
// if the until condition is reached)
|
||||||
|
if st == siblingNextUntil || st == siblingPrevUntil {
|
||||||
|
if untilFunc(c) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
result = append(result, c)
|
||||||
|
if st == siblingNext || st == siblingPrev {
|
||||||
|
// Only one node was requested (immediate next or previous), so exit
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Internal implementation of parent nodes that return a raw slice of Nodes.
|
||||||
|
func getParentNodes(nodes []*html.Node) []*html.Node {
|
||||||
|
return mapNodes(nodes, func(i int, n *html.Node) []*html.Node {
|
||||||
|
if n.Parent != nil && n.Parent.Type == html.ElementNode {
|
||||||
|
return []*html.Node{n.Parent}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// Internal map function used by many traversing methods. Takes the source nodes
|
||||||
|
// to iterate on and the mapping function that returns an array of nodes.
|
||||||
|
// Returns an array of nodes mapped by calling the callback function once for
|
||||||
|
// each node in the source nodes.
|
||||||
|
func mapNodes(nodes []*html.Node, f func(int, *html.Node) []*html.Node) (result []*html.Node) {
|
||||||
|
for i, n := range nodes {
|
||||||
|
if vals := f(i, n); len(vals) > 0 {
|
||||||
|
result = appendWithoutDuplicates(result, vals)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
697
Godeps/_workspace/src/github.com/PuerkitoBio/goquery/traversal_test.go
generated
vendored
Normal file
697
Godeps/_workspace/src/github.com/PuerkitoBio/goquery/traversal_test.go
generated
vendored
Normal file
|
@ -0,0 +1,697 @@
|
||||||
|
package goquery
|
||||||
|
|
||||||
|
import (
|
||||||
|
"strings"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestFind(t *testing.T) {
|
||||||
|
sel := Doc().Find("div.row-fluid")
|
||||||
|
assertLength(t, sel.Nodes, 9)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestFindRollback(t *testing.T) {
|
||||||
|
sel := Doc().Find("div.row-fluid")
|
||||||
|
sel2 := sel.Find("a").End()
|
||||||
|
assertEqual(t, sel, sel2)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestFindNotSelf(t *testing.T) {
|
||||||
|
sel := Doc().Find("h1").Find("h1")
|
||||||
|
assertLength(t, sel.Nodes, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestFindInvalidSelector(t *testing.T) {
|
||||||
|
defer assertPanic(t)
|
||||||
|
Doc().Find(":+ ^")
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestChainedFind(t *testing.T) {
|
||||||
|
sel := Doc().Find("div.hero-unit").Find(".row-fluid")
|
||||||
|
assertLength(t, sel.Nodes, 4)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestChildren(t *testing.T) {
|
||||||
|
sel := Doc().Find(".pvk-content").Children()
|
||||||
|
assertLength(t, sel.Nodes, 5)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestChildrenRollback(t *testing.T) {
|
||||||
|
sel := Doc().Find(".pvk-content")
|
||||||
|
sel2 := sel.Children().End()
|
||||||
|
assertEqual(t, sel, sel2)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestContents(t *testing.T) {
|
||||||
|
sel := Doc().Find(".pvk-content").Contents()
|
||||||
|
assertLength(t, sel.Nodes, 13)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestContentsRollback(t *testing.T) {
|
||||||
|
sel := Doc().Find(".pvk-content")
|
||||||
|
sel2 := sel.Contents().End()
|
||||||
|
assertEqual(t, sel, sel2)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestChildrenFiltered(t *testing.T) {
|
||||||
|
sel := Doc().Find(".pvk-content").ChildrenFiltered(".hero-unit")
|
||||||
|
assertLength(t, sel.Nodes, 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestChildrenFilteredRollback(t *testing.T) {
|
||||||
|
sel := Doc().Find(".pvk-content")
|
||||||
|
sel2 := sel.ChildrenFiltered(".hero-unit").End()
|
||||||
|
assertEqual(t, sel, sel2)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestContentsFiltered(t *testing.T) {
|
||||||
|
sel := Doc().Find(".pvk-content").ContentsFiltered(".hero-unit")
|
||||||
|
assertLength(t, sel.Nodes, 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestContentsFilteredRollback(t *testing.T) {
|
||||||
|
sel := Doc().Find(".pvk-content")
|
||||||
|
sel2 := sel.ContentsFiltered(".hero-unit").End()
|
||||||
|
assertEqual(t, sel, sel2)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestChildrenFilteredNone(t *testing.T) {
|
||||||
|
sel := Doc().Find(".pvk-content").ChildrenFiltered("a.btn")
|
||||||
|
assertLength(t, sel.Nodes, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestParent(t *testing.T) {
|
||||||
|
sel := Doc().Find(".container-fluid").Parent()
|
||||||
|
assertLength(t, sel.Nodes, 3)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestParentRollback(t *testing.T) {
|
||||||
|
sel := Doc().Find(".container-fluid")
|
||||||
|
sel2 := sel.Parent().End()
|
||||||
|
assertEqual(t, sel, sel2)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestParentBody(t *testing.T) {
|
||||||
|
sel := Doc().Find("body").Parent()
|
||||||
|
assertLength(t, sel.Nodes, 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestParentFiltered(t *testing.T) {
|
||||||
|
sel := Doc().Find(".container-fluid").ParentFiltered(".hero-unit")
|
||||||
|
assertLength(t, sel.Nodes, 1)
|
||||||
|
assertClass(t, sel, "hero-unit")
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestParentFilteredRollback(t *testing.T) {
|
||||||
|
sel := Doc().Find(".container-fluid")
|
||||||
|
sel2 := sel.ParentFiltered(".hero-unit").End()
|
||||||
|
assertEqual(t, sel, sel2)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestParents(t *testing.T) {
|
||||||
|
sel := Doc().Find(".container-fluid").Parents()
|
||||||
|
assertLength(t, sel.Nodes, 8)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestParentsOrder(t *testing.T) {
|
||||||
|
sel := Doc().Find("#cf2").Parents()
|
||||||
|
assertLength(t, sel.Nodes, 6)
|
||||||
|
assertSelectionIs(t, sel, ".hero-unit", ".pvk-content", "div.row-fluid", "#cf1", "body", "html")
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestParentsRollback(t *testing.T) {
|
||||||
|
sel := Doc().Find(".container-fluid")
|
||||||
|
sel2 := sel.Parents().End()
|
||||||
|
assertEqual(t, sel, sel2)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestParentsFiltered(t *testing.T) {
|
||||||
|
sel := Doc().Find(".container-fluid").ParentsFiltered("body")
|
||||||
|
assertLength(t, sel.Nodes, 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestParentsFilteredRollback(t *testing.T) {
|
||||||
|
sel := Doc().Find(".container-fluid")
|
||||||
|
sel2 := sel.ParentsFiltered("body").End()
|
||||||
|
assertEqual(t, sel, sel2)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestParentsUntil(t *testing.T) {
|
||||||
|
sel := Doc().Find(".container-fluid").ParentsUntil("body")
|
||||||
|
assertLength(t, sel.Nodes, 6)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestParentsUntilRollback(t *testing.T) {
|
||||||
|
sel := Doc().Find(".container-fluid")
|
||||||
|
sel2 := sel.ParentsUntil("body").End()
|
||||||
|
assertEqual(t, sel, sel2)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestParentsUntilSelection(t *testing.T) {
|
||||||
|
sel := Doc().Find(".container-fluid")
|
||||||
|
sel2 := Doc().Find(".pvk-content")
|
||||||
|
sel = sel.ParentsUntilSelection(sel2)
|
||||||
|
assertLength(t, sel.Nodes, 3)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestParentsUntilSelectionRollback(t *testing.T) {
|
||||||
|
sel := Doc().Find(".container-fluid")
|
||||||
|
sel2 := Doc().Find(".pvk-content")
|
||||||
|
sel2 = sel.ParentsUntilSelection(sel2).End()
|
||||||
|
assertEqual(t, sel, sel2)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestParentsUntilNodes(t *testing.T) {
|
||||||
|
sel := Doc().Find(".container-fluid")
|
||||||
|
sel2 := Doc().Find(".pvk-content, .hero-unit")
|
||||||
|
sel = sel.ParentsUntilNodes(sel2.Nodes...)
|
||||||
|
assertLength(t, sel.Nodes, 2)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestParentsUntilNodesRollback(t *testing.T) {
|
||||||
|
sel := Doc().Find(".container-fluid")
|
||||||
|
sel2 := Doc().Find(".pvk-content, .hero-unit")
|
||||||
|
sel2 = sel.ParentsUntilNodes(sel2.Nodes...).End()
|
||||||
|
assertEqual(t, sel, sel2)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestParentsFilteredUntil(t *testing.T) {
|
||||||
|
sel := Doc().Find(".container-fluid").ParentsFilteredUntil(".pvk-content", "body")
|
||||||
|
assertLength(t, sel.Nodes, 2)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestParentsFilteredUntilRollback(t *testing.T) {
|
||||||
|
sel := Doc().Find(".container-fluid")
|
||||||
|
sel2 := sel.ParentsFilteredUntil(".pvk-content", "body").End()
|
||||||
|
assertEqual(t, sel, sel2)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestParentsFilteredUntilSelection(t *testing.T) {
|
||||||
|
sel := Doc().Find(".container-fluid")
|
||||||
|
sel2 := Doc().Find(".row-fluid")
|
||||||
|
sel = sel.ParentsFilteredUntilSelection("div", sel2)
|
||||||
|
assertLength(t, sel.Nodes, 3)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestParentsFilteredUntilSelectionRollback(t *testing.T) {
|
||||||
|
sel := Doc().Find(".container-fluid")
|
||||||
|
sel2 := Doc().Find(".row-fluid")
|
||||||
|
sel2 = sel.ParentsFilteredUntilSelection("div", sel2).End()
|
||||||
|
assertEqual(t, sel, sel2)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestParentsFilteredUntilNodes(t *testing.T) {
|
||||||
|
sel := Doc().Find(".container-fluid")
|
||||||
|
sel2 := Doc().Find(".row-fluid")
|
||||||
|
sel = sel.ParentsFilteredUntilNodes("body", sel2.Nodes...)
|
||||||
|
assertLength(t, sel.Nodes, 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestParentsFilteredUntilNodesRollback(t *testing.T) {
|
||||||
|
sel := Doc().Find(".container-fluid")
|
||||||
|
sel2 := Doc().Find(".row-fluid")
|
||||||
|
sel2 = sel.ParentsFilteredUntilNodes("body", sel2.Nodes...).End()
|
||||||
|
assertEqual(t, sel, sel2)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSiblings(t *testing.T) {
|
||||||
|
sel := Doc().Find("h1").Siblings()
|
||||||
|
assertLength(t, sel.Nodes, 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSiblingsRollback(t *testing.T) {
|
||||||
|
sel := Doc().Find("h1")
|
||||||
|
sel2 := sel.Siblings().End()
|
||||||
|
assertEqual(t, sel, sel2)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSiblings2(t *testing.T) {
|
||||||
|
sel := Doc().Find(".pvk-gutter").Siblings()
|
||||||
|
assertLength(t, sel.Nodes, 9)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSiblings3(t *testing.T) {
|
||||||
|
sel := Doc().Find("body>.container-fluid").Siblings()
|
||||||
|
assertLength(t, sel.Nodes, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSiblingsFiltered(t *testing.T) {
|
||||||
|
sel := Doc().Find(".pvk-gutter").SiblingsFiltered(".pvk-content")
|
||||||
|
assertLength(t, sel.Nodes, 3)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSiblingsFilteredRollback(t *testing.T) {
|
||||||
|
sel := Doc().Find(".pvk-gutter")
|
||||||
|
sel2 := sel.SiblingsFiltered(".pvk-content").End()
|
||||||
|
assertEqual(t, sel, sel2)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestNext(t *testing.T) {
|
||||||
|
sel := Doc().Find("h1").Next()
|
||||||
|
assertLength(t, sel.Nodes, 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestNextRollback(t *testing.T) {
|
||||||
|
sel := Doc().Find("h1")
|
||||||
|
sel2 := sel.Next().End()
|
||||||
|
assertEqual(t, sel, sel2)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestNext2(t *testing.T) {
|
||||||
|
sel := Doc().Find(".close").Next()
|
||||||
|
assertLength(t, sel.Nodes, 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestNextNone(t *testing.T) {
|
||||||
|
sel := Doc().Find("small").Next()
|
||||||
|
assertLength(t, sel.Nodes, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestNextFiltered(t *testing.T) {
|
||||||
|
sel := Doc().Find(".container-fluid").NextFiltered("div")
|
||||||
|
assertLength(t, sel.Nodes, 2)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestNextFilteredRollback(t *testing.T) {
|
||||||
|
sel := Doc().Find(".container-fluid")
|
||||||
|
sel2 := sel.NextFiltered("div").End()
|
||||||
|
assertEqual(t, sel, sel2)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestNextFiltered2(t *testing.T) {
|
||||||
|
sel := Doc().Find(".container-fluid").NextFiltered("[ng-view]")
|
||||||
|
assertLength(t, sel.Nodes, 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestPrev(t *testing.T) {
|
||||||
|
sel := Doc().Find(".red").Prev()
|
||||||
|
assertLength(t, sel.Nodes, 1)
|
||||||
|
assertClass(t, sel, "green")
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestPrevRollback(t *testing.T) {
|
||||||
|
sel := Doc().Find(".red")
|
||||||
|
sel2 := sel.Prev().End()
|
||||||
|
assertEqual(t, sel, sel2)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestPrev2(t *testing.T) {
|
||||||
|
sel := Doc().Find(".row-fluid").Prev()
|
||||||
|
assertLength(t, sel.Nodes, 5)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestPrevNone(t *testing.T) {
|
||||||
|
sel := Doc().Find("h2").Prev()
|
||||||
|
assertLength(t, sel.Nodes, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestPrevFiltered(t *testing.T) {
|
||||||
|
sel := Doc().Find(".row-fluid").PrevFiltered(".row-fluid")
|
||||||
|
assertLength(t, sel.Nodes, 5)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestPrevFilteredRollback(t *testing.T) {
|
||||||
|
sel := Doc().Find(".row-fluid")
|
||||||
|
sel2 := sel.PrevFiltered(".row-fluid").End()
|
||||||
|
assertEqual(t, sel, sel2)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestNextAll(t *testing.T) {
|
||||||
|
sel := Doc().Find("#cf2 div:nth-child(1)").NextAll()
|
||||||
|
assertLength(t, sel.Nodes, 3)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestNextAllRollback(t *testing.T) {
|
||||||
|
sel := Doc().Find("#cf2 div:nth-child(1)")
|
||||||
|
sel2 := sel.NextAll().End()
|
||||||
|
assertEqual(t, sel, sel2)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestNextAll2(t *testing.T) {
|
||||||
|
sel := Doc().Find("div[ng-cloak]").NextAll()
|
||||||
|
assertLength(t, sel.Nodes, 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestNextAllNone(t *testing.T) {
|
||||||
|
sel := Doc().Find(".footer").NextAll()
|
||||||
|
assertLength(t, sel.Nodes, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestNextAllFiltered(t *testing.T) {
|
||||||
|
sel := Doc().Find("#cf2 .row-fluid").NextAllFiltered("[ng-cloak]")
|
||||||
|
assertLength(t, sel.Nodes, 2)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestNextAllFilteredRollback(t *testing.T) {
|
||||||
|
sel := Doc().Find("#cf2 .row-fluid")
|
||||||
|
sel2 := sel.NextAllFiltered("[ng-cloak]").End()
|
||||||
|
assertEqual(t, sel, sel2)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestNextAllFiltered2(t *testing.T) {
|
||||||
|
sel := Doc().Find(".close").NextAllFiltered("h4")
|
||||||
|
assertLength(t, sel.Nodes, 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestPrevAll(t *testing.T) {
|
||||||
|
sel := Doc().Find("[ng-view]").PrevAll()
|
||||||
|
assertLength(t, sel.Nodes, 2)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestPrevAllOrder(t *testing.T) {
|
||||||
|
sel := Doc().Find("[ng-view]").PrevAll()
|
||||||
|
assertLength(t, sel.Nodes, 2)
|
||||||
|
assertSelectionIs(t, sel, "#cf4", "#cf3")
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestPrevAllRollback(t *testing.T) {
|
||||||
|
sel := Doc().Find("[ng-view]")
|
||||||
|
sel2 := sel.PrevAll().End()
|
||||||
|
assertEqual(t, sel, sel2)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestPrevAll2(t *testing.T) {
|
||||||
|
sel := Doc().Find(".pvk-gutter").PrevAll()
|
||||||
|
assertLength(t, sel.Nodes, 6)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestPrevAllFiltered(t *testing.T) {
|
||||||
|
sel := Doc().Find(".pvk-gutter").PrevAllFiltered(".pvk-content")
|
||||||
|
assertLength(t, sel.Nodes, 3)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestPrevAllFilteredRollback(t *testing.T) {
|
||||||
|
sel := Doc().Find(".pvk-gutter")
|
||||||
|
sel2 := sel.PrevAllFiltered(".pvk-content").End()
|
||||||
|
assertEqual(t, sel, sel2)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestNextUntil(t *testing.T) {
|
||||||
|
sel := Doc().Find(".alert a").NextUntil("p")
|
||||||
|
assertLength(t, sel.Nodes, 1)
|
||||||
|
assertSelectionIs(t, sel, "h4")
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestNextUntil2(t *testing.T) {
|
||||||
|
sel := Doc().Find("#cf2-1").NextUntil("[ng-cloak]")
|
||||||
|
assertLength(t, sel.Nodes, 1)
|
||||||
|
assertSelectionIs(t, sel, "#cf2-2")
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestNextUntilOrder(t *testing.T) {
|
||||||
|
sel := Doc().Find("#cf2-1").NextUntil("#cf2-4")
|
||||||
|
assertLength(t, sel.Nodes, 2)
|
||||||
|
assertSelectionIs(t, sel, "#cf2-2", "#cf2-3")
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestNextUntilRollback(t *testing.T) {
|
||||||
|
sel := Doc().Find("#cf2-1")
|
||||||
|
sel2 := sel.PrevUntil("#cf2-4").End()
|
||||||
|
assertEqual(t, sel, sel2)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestNextUntilSelection(t *testing.T) {
|
||||||
|
sel := Doc2().Find("#n2")
|
||||||
|
sel2 := Doc2().Find("#n4")
|
||||||
|
sel2 = sel.NextUntilSelection(sel2)
|
||||||
|
assertLength(t, sel2.Nodes, 1)
|
||||||
|
assertSelectionIs(t, sel2, "#n3")
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestNextUntilSelectionRollback(t *testing.T) {
|
||||||
|
sel := Doc2().Find("#n2")
|
||||||
|
sel2 := Doc2().Find("#n4")
|
||||||
|
sel2 = sel.NextUntilSelection(sel2).End()
|
||||||
|
assertEqual(t, sel, sel2)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestNextUntilNodes(t *testing.T) {
|
||||||
|
sel := Doc2().Find("#n2")
|
||||||
|
sel2 := Doc2().Find("#n5")
|
||||||
|
sel2 = sel.NextUntilNodes(sel2.Nodes...)
|
||||||
|
assertLength(t, sel2.Nodes, 2)
|
||||||
|
assertSelectionIs(t, sel2, "#n3", "#n4")
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestNextUntilNodesRollback(t *testing.T) {
|
||||||
|
sel := Doc2().Find("#n2")
|
||||||
|
sel2 := Doc2().Find("#n5")
|
||||||
|
sel2 = sel.NextUntilNodes(sel2.Nodes...).End()
|
||||||
|
assertEqual(t, sel, sel2)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestPrevUntil(t *testing.T) {
|
||||||
|
sel := Doc().Find(".alert p").PrevUntil("a")
|
||||||
|
assertLength(t, sel.Nodes, 1)
|
||||||
|
assertSelectionIs(t, sel, "h4")
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestPrevUntil2(t *testing.T) {
|
||||||
|
sel := Doc().Find("[ng-cloak]").PrevUntil(":not([ng-cloak])")
|
||||||
|
assertLength(t, sel.Nodes, 1)
|
||||||
|
assertSelectionIs(t, sel, "[ng-cloak]")
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestPrevUntilOrder(t *testing.T) {
|
||||||
|
sel := Doc().Find("#cf2-4").PrevUntil("#cf2-1")
|
||||||
|
assertLength(t, sel.Nodes, 2)
|
||||||
|
assertSelectionIs(t, sel, "#cf2-3", "#cf2-2")
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestPrevUntilRollback(t *testing.T) {
|
||||||
|
sel := Doc().Find("#cf2-4")
|
||||||
|
sel2 := sel.PrevUntil("#cf2-1").End()
|
||||||
|
assertEqual(t, sel, sel2)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestPrevUntilSelection(t *testing.T) {
|
||||||
|
sel := Doc2().Find("#n4")
|
||||||
|
sel2 := Doc2().Find("#n2")
|
||||||
|
sel2 = sel.PrevUntilSelection(sel2)
|
||||||
|
assertLength(t, sel2.Nodes, 1)
|
||||||
|
assertSelectionIs(t, sel2, "#n3")
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestPrevUntilSelectionRollback(t *testing.T) {
|
||||||
|
sel := Doc2().Find("#n4")
|
||||||
|
sel2 := Doc2().Find("#n2")
|
||||||
|
sel2 = sel.PrevUntilSelection(sel2).End()
|
||||||
|
assertEqual(t, sel, sel2)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestPrevUntilNodes(t *testing.T) {
|
||||||
|
sel := Doc2().Find("#n5")
|
||||||
|
sel2 := Doc2().Find("#n2")
|
||||||
|
sel2 = sel.PrevUntilNodes(sel2.Nodes...)
|
||||||
|
assertLength(t, sel2.Nodes, 2)
|
||||||
|
assertSelectionIs(t, sel2, "#n4", "#n3")
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestPrevUntilNodesRollback(t *testing.T) {
|
||||||
|
sel := Doc2().Find("#n5")
|
||||||
|
sel2 := Doc2().Find("#n2")
|
||||||
|
sel2 = sel.PrevUntilNodes(sel2.Nodes...).End()
|
||||||
|
assertEqual(t, sel, sel2)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestNextFilteredUntil(t *testing.T) {
|
||||||
|
sel := Doc2().Find(".two").NextFilteredUntil(".even", ".six")
|
||||||
|
assertLength(t, sel.Nodes, 4)
|
||||||
|
assertSelectionIs(t, sel, "#n3", "#n5", "#nf3", "#nf5")
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestNextFilteredUntilRollback(t *testing.T) {
|
||||||
|
sel := Doc2().Find(".two")
|
||||||
|
sel2 := sel.NextFilteredUntil(".even", ".six").End()
|
||||||
|
assertEqual(t, sel, sel2)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestNextFilteredUntilSelection(t *testing.T) {
|
||||||
|
sel := Doc2().Find(".even")
|
||||||
|
sel2 := Doc2().Find(".five")
|
||||||
|
sel = sel.NextFilteredUntilSelection(".even", sel2)
|
||||||
|
assertLength(t, sel.Nodes, 2)
|
||||||
|
assertSelectionIs(t, sel, "#n3", "#nf3")
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestNextFilteredUntilSelectionRollback(t *testing.T) {
|
||||||
|
sel := Doc2().Find(".even")
|
||||||
|
sel2 := Doc2().Find(".five")
|
||||||
|
sel3 := sel.NextFilteredUntilSelection(".even", sel2).End()
|
||||||
|
assertEqual(t, sel, sel3)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestNextFilteredUntilNodes(t *testing.T) {
|
||||||
|
sel := Doc2().Find(".even")
|
||||||
|
sel2 := Doc2().Find(".four")
|
||||||
|
sel = sel.NextFilteredUntilNodes(".odd", sel2.Nodes...)
|
||||||
|
assertLength(t, sel.Nodes, 4)
|
||||||
|
assertSelectionIs(t, sel, "#n2", "#n6", "#nf2", "#nf6")
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestNextFilteredUntilNodesRollback(t *testing.T) {
|
||||||
|
sel := Doc2().Find(".even")
|
||||||
|
sel2 := Doc2().Find(".four")
|
||||||
|
sel3 := sel.NextFilteredUntilNodes(".odd", sel2.Nodes...).End()
|
||||||
|
assertEqual(t, sel, sel3)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestPrevFilteredUntil(t *testing.T) {
|
||||||
|
sel := Doc2().Find(".five").PrevFilteredUntil(".odd", ".one")
|
||||||
|
assertLength(t, sel.Nodes, 4)
|
||||||
|
assertSelectionIs(t, sel, "#n4", "#n2", "#nf4", "#nf2")
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestPrevFilteredUntilRollback(t *testing.T) {
|
||||||
|
sel := Doc2().Find(".four")
|
||||||
|
sel2 := sel.PrevFilteredUntil(".odd", ".one").End()
|
||||||
|
assertEqual(t, sel, sel2)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestPrevFilteredUntilSelection(t *testing.T) {
|
||||||
|
sel := Doc2().Find(".odd")
|
||||||
|
sel2 := Doc2().Find(".two")
|
||||||
|
sel = sel.PrevFilteredUntilSelection(".odd", sel2)
|
||||||
|
assertLength(t, sel.Nodes, 2)
|
||||||
|
assertSelectionIs(t, sel, "#n4", "#nf4")
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestPrevFilteredUntilSelectionRollback(t *testing.T) {
|
||||||
|
sel := Doc2().Find(".even")
|
||||||
|
sel2 := Doc2().Find(".five")
|
||||||
|
sel3 := sel.PrevFilteredUntilSelection(".even", sel2).End()
|
||||||
|
assertEqual(t, sel, sel3)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestPrevFilteredUntilNodes(t *testing.T) {
|
||||||
|
sel := Doc2().Find(".even")
|
||||||
|
sel2 := Doc2().Find(".four")
|
||||||
|
sel = sel.PrevFilteredUntilNodes(".odd", sel2.Nodes...)
|
||||||
|
assertLength(t, sel.Nodes, 2)
|
||||||
|
assertSelectionIs(t, sel, "#n2", "#nf2")
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestPrevFilteredUntilNodesRollback(t *testing.T) {
|
||||||
|
sel := Doc2().Find(".even")
|
||||||
|
sel2 := Doc2().Find(".four")
|
||||||
|
sel3 := sel.PrevFilteredUntilNodes(".odd", sel2.Nodes...).End()
|
||||||
|
assertEqual(t, sel, sel3)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestClosestItself(t *testing.T) {
|
||||||
|
sel := Doc2().Find(".three")
|
||||||
|
sel2 := sel.Closest(".row")
|
||||||
|
assertLength(t, sel2.Nodes, sel.Length())
|
||||||
|
assertSelectionIs(t, sel2, "#n3", "#nf3")
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestClosestNoDupes(t *testing.T) {
|
||||||
|
sel := Doc().Find(".span12")
|
||||||
|
sel2 := sel.Closest(".pvk-content")
|
||||||
|
assertLength(t, sel2.Nodes, 1)
|
||||||
|
assertClass(t, sel2, "pvk-content")
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestClosestNone(t *testing.T) {
|
||||||
|
sel := Doc().Find("h4")
|
||||||
|
sel2 := sel.Closest("a")
|
||||||
|
assertLength(t, sel2.Nodes, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestClosestMany(t *testing.T) {
|
||||||
|
sel := Doc().Find(".container-fluid")
|
||||||
|
sel2 := sel.Closest(".pvk-content")
|
||||||
|
assertLength(t, sel2.Nodes, 2)
|
||||||
|
assertSelectionIs(t, sel2, "#pc1", "#pc2")
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestClosestRollback(t *testing.T) {
|
||||||
|
sel := Doc().Find(".container-fluid")
|
||||||
|
sel2 := sel.Closest(".pvk-content").End()
|
||||||
|
assertEqual(t, sel, sel2)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestClosestSelectionItself(t *testing.T) {
|
||||||
|
sel := Doc2().Find(".three")
|
||||||
|
sel2 := sel.ClosestSelection(Doc2().Find(".row"))
|
||||||
|
assertLength(t, sel2.Nodes, sel.Length())
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestClosestSelectionNoDupes(t *testing.T) {
|
||||||
|
sel := Doc().Find(".span12")
|
||||||
|
sel2 := sel.ClosestSelection(Doc().Find(".pvk-content"))
|
||||||
|
assertLength(t, sel2.Nodes, 1)
|
||||||
|
assertClass(t, sel2, "pvk-content")
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestClosestSelectionNone(t *testing.T) {
|
||||||
|
sel := Doc().Find("h4")
|
||||||
|
sel2 := sel.ClosestSelection(Doc().Find("a"))
|
||||||
|
assertLength(t, sel2.Nodes, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestClosestSelectionMany(t *testing.T) {
|
||||||
|
sel := Doc().Find(".container-fluid")
|
||||||
|
sel2 := sel.ClosestSelection(Doc().Find(".pvk-content"))
|
||||||
|
assertLength(t, sel2.Nodes, 2)
|
||||||
|
assertSelectionIs(t, sel2, "#pc1", "#pc2")
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestClosestSelectionRollback(t *testing.T) {
|
||||||
|
sel := Doc().Find(".container-fluid")
|
||||||
|
sel2 := sel.ClosestSelection(Doc().Find(".pvk-content")).End()
|
||||||
|
assertEqual(t, sel, sel2)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestClosestNodesItself(t *testing.T) {
|
||||||
|
sel := Doc2().Find(".three")
|
||||||
|
sel2 := sel.ClosestNodes(Doc2().Find(".row").Nodes...)
|
||||||
|
assertLength(t, sel2.Nodes, sel.Length())
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestClosestNodesNoDupes(t *testing.T) {
|
||||||
|
sel := Doc().Find(".span12")
|
||||||
|
sel2 := sel.ClosestNodes(Doc().Find(".pvk-content").Nodes...)
|
||||||
|
assertLength(t, sel2.Nodes, 1)
|
||||||
|
assertClass(t, sel2, "pvk-content")
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestClosestNodesNone(t *testing.T) {
|
||||||
|
sel := Doc().Find("h4")
|
||||||
|
sel2 := sel.ClosestNodes(Doc().Find("a").Nodes...)
|
||||||
|
assertLength(t, sel2.Nodes, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestClosestNodesMany(t *testing.T) {
|
||||||
|
sel := Doc().Find(".container-fluid")
|
||||||
|
sel2 := sel.ClosestNodes(Doc().Find(".pvk-content").Nodes...)
|
||||||
|
assertLength(t, sel2.Nodes, 2)
|
||||||
|
assertSelectionIs(t, sel2, "#pc1", "#pc2")
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestClosestNodesRollback(t *testing.T) {
|
||||||
|
sel := Doc().Find(".container-fluid")
|
||||||
|
sel2 := sel.ClosestNodes(Doc().Find(".pvk-content").Nodes...).End()
|
||||||
|
assertEqual(t, sel, sel2)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestIssue26(t *testing.T) {
|
||||||
|
img1 := `<img src="assets/images/gallery/thumb-1.jpg" alt="150x150" />`
|
||||||
|
img2 := `<img alt="150x150" src="assets/images/gallery/thumb-1.jpg" />`
|
||||||
|
cases := []struct {
|
||||||
|
s string
|
||||||
|
l int
|
||||||
|
}{
|
||||||
|
{s: img1 + img2, l: 2},
|
||||||
|
{s: img1, l: 1},
|
||||||
|
{s: img2, l: 1},
|
||||||
|
}
|
||||||
|
for _, c := range cases {
|
||||||
|
doc, err := NewDocumentFromReader(strings.NewReader(c.s))
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
sel := doc.Find("img[src]")
|
||||||
|
assertLength(t, sel.Nodes, c.l)
|
||||||
|
}
|
||||||
|
}
|
113
Godeps/_workspace/src/github.com/PuerkitoBio/goquery/type.go
generated
vendored
Normal file
113
Godeps/_workspace/src/github.com/PuerkitoBio/goquery/type.go
generated
vendored
Normal file
|
@ -0,0 +1,113 @@
|
||||||
|
package goquery
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"io"
|
||||||
|
"net/http"
|
||||||
|
"net/url"
|
||||||
|
|
||||||
|
"golang.org/x/net/html"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Document represents an HTML document to be manipulated. Unlike jQuery, which
|
||||||
|
// is loaded as part of a DOM document, and thus acts upon its containing
|
||||||
|
// document, GoQuery doesn't know which HTML document to act upon. So it needs
|
||||||
|
// to be told, and that's what the Document class is for. It holds the root
|
||||||
|
// document node to manipulate, and can make selections on this document.
|
||||||
|
type Document struct {
|
||||||
|
*Selection
|
||||||
|
Url *url.URL
|
||||||
|
rootNode *html.Node
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewDocumentFromNode is a Document constructor that takes a root html Node
|
||||||
|
// as argument.
|
||||||
|
func NewDocumentFromNode(root *html.Node) *Document {
|
||||||
|
return newDocument(root, nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewDocument is a Document constructor that takes a string URL as argument.
|
||||||
|
// It loads the specified document, parses it, and stores the root Document
|
||||||
|
// node, ready to be manipulated.
|
||||||
|
func NewDocument(url string) (*Document, error) {
|
||||||
|
// Load the URL
|
||||||
|
res, e := http.Get(url)
|
||||||
|
if e != nil {
|
||||||
|
return nil, e
|
||||||
|
}
|
||||||
|
return NewDocumentFromResponse(res)
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewDocumentFromReader returns a Document from a generic reader.
|
||||||
|
// It returns an error as second value if the reader's data cannot be parsed
|
||||||
|
// as html. It does *not* check if the reader is also an io.Closer, so the
|
||||||
|
// provided reader is never closed by this call, it is the responsibility
|
||||||
|
// of the caller to close it if required.
|
||||||
|
func NewDocumentFromReader(r io.Reader) (*Document, error) {
|
||||||
|
root, e := html.Parse(r)
|
||||||
|
if e != nil {
|
||||||
|
return nil, e
|
||||||
|
}
|
||||||
|
return newDocument(root, nil), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewDocumentFromResponse is another Document constructor that takes an http response as argument.
|
||||||
|
// It loads the specified response's document, parses it, and stores the root Document
|
||||||
|
// node, ready to be manipulated. The response's body is closed on return.
|
||||||
|
func NewDocumentFromResponse(res *http.Response) (*Document, error) {
|
||||||
|
if res == nil {
|
||||||
|
return nil, errors.New("Response is nil pointer")
|
||||||
|
}
|
||||||
|
|
||||||
|
defer res.Body.Close()
|
||||||
|
|
||||||
|
// Parse the HTML into nodes
|
||||||
|
root, e := html.Parse(res.Body)
|
||||||
|
if e != nil {
|
||||||
|
return nil, e
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create and fill the document
|
||||||
|
return newDocument(root, res.Request.URL), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// CloneDocument creates a deep-clone of a document.
|
||||||
|
func CloneDocument(doc *Document) *Document {
|
||||||
|
return newDocument(cloneNode(doc.rootNode), doc.Url)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Private constructor, make sure all fields are correctly filled.
|
||||||
|
func newDocument(root *html.Node, url *url.URL) *Document {
|
||||||
|
// Create and fill the document
|
||||||
|
d := &Document{nil, url, root}
|
||||||
|
d.Selection = newSingleSelection(root, d)
|
||||||
|
return d
|
||||||
|
}
|
||||||
|
|
||||||
|
// Selection represents a collection of nodes matching some criteria. The
|
||||||
|
// initial Selection can be created by using Document.Find, and then
|
||||||
|
// manipulated using the jQuery-like chainable syntax and methods.
|
||||||
|
type Selection struct {
|
||||||
|
Nodes []*html.Node
|
||||||
|
document *Document
|
||||||
|
prevSel *Selection
|
||||||
|
}
|
||||||
|
|
||||||
|
// Helper constructor to create an empty selection
|
||||||
|
func newEmptySelection(doc *Document) *Selection {
|
||||||
|
return &Selection{nil, doc, nil}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Helper constructor to create a selection of only one node
|
||||||
|
func newSingleSelection(node *html.Node, doc *Document) *Selection {
|
||||||
|
return &Selection{[]*html.Node{node}, doc, nil}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Matcher is an interface that defines the methods to match
|
||||||
|
// HTML nodes against a compiled selector string. Cascadia's
|
||||||
|
// Selector implements this interface.
|
||||||
|
type Matcher interface {
|
||||||
|
Match(*html.Node) bool
|
||||||
|
MatchAll(*html.Node) []*html.Node
|
||||||
|
Filter([]*html.Node) []*html.Node
|
||||||
|
}
|
192
Godeps/_workspace/src/github.com/PuerkitoBio/goquery/type_test.go
generated
vendored
Normal file
192
Godeps/_workspace/src/github.com/PuerkitoBio/goquery/type_test.go
generated
vendored
Normal file
|
@ -0,0 +1,192 @@
|
||||||
|
package goquery
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"golang.org/x/net/html"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Test helper functions and members
|
||||||
|
var doc *Document
|
||||||
|
var doc2 *Document
|
||||||
|
var doc3 *Document
|
||||||
|
var docB *Document
|
||||||
|
var docW *Document
|
||||||
|
|
||||||
|
func Doc() *Document {
|
||||||
|
if doc == nil {
|
||||||
|
doc = loadDoc("page.html")
|
||||||
|
}
|
||||||
|
return doc
|
||||||
|
}
|
||||||
|
func DocClone() *Document {
|
||||||
|
return CloneDocument(Doc())
|
||||||
|
}
|
||||||
|
func Doc2() *Document {
|
||||||
|
if doc2 == nil {
|
||||||
|
doc2 = loadDoc("page2.html")
|
||||||
|
}
|
||||||
|
return doc2
|
||||||
|
}
|
||||||
|
func Doc2Clone() *Document {
|
||||||
|
return CloneDocument(Doc2())
|
||||||
|
}
|
||||||
|
func Doc3() *Document {
|
||||||
|
if doc3 == nil {
|
||||||
|
doc3 = loadDoc("page3.html")
|
||||||
|
}
|
||||||
|
return doc3
|
||||||
|
}
|
||||||
|
func Doc3Clone() *Document {
|
||||||
|
return CloneDocument(Doc3())
|
||||||
|
}
|
||||||
|
func DocB() *Document {
|
||||||
|
if docB == nil {
|
||||||
|
docB = loadDoc("gotesting.html")
|
||||||
|
}
|
||||||
|
return docB
|
||||||
|
}
|
||||||
|
func DocBClone() *Document {
|
||||||
|
return CloneDocument(DocB())
|
||||||
|
}
|
||||||
|
func DocW() *Document {
|
||||||
|
if docW == nil {
|
||||||
|
docW = loadDoc("gowiki.html")
|
||||||
|
}
|
||||||
|
return docW
|
||||||
|
}
|
||||||
|
func DocWClone() *Document {
|
||||||
|
return CloneDocument(DocW())
|
||||||
|
}
|
||||||
|
|
||||||
|
func assertLength(t *testing.T, nodes []*html.Node, length int) {
|
||||||
|
if len(nodes) != length {
|
||||||
|
t.Errorf("Expected %d nodes, found %d.", length, len(nodes))
|
||||||
|
for i, n := range nodes {
|
||||||
|
t.Logf("Node %d: %+v.", i, n)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func assertClass(t *testing.T, sel *Selection, class string) {
|
||||||
|
if !sel.HasClass(class) {
|
||||||
|
t.Errorf("Expected node to have class %s, found %+v.", class, sel.Get(0))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func assertPanic(t *testing.T) {
|
||||||
|
if e := recover(); e == nil {
|
||||||
|
t.Error("Expected a panic.")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func assertEqual(t *testing.T, s1 *Selection, s2 *Selection) {
|
||||||
|
if s1 != s2 {
|
||||||
|
t.Error("Expected selection objects to be the same.")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func assertSelectionIs(t *testing.T, sel *Selection, is ...string) {
|
||||||
|
for i := 0; i < sel.Length(); i++ {
|
||||||
|
if !sel.Eq(i).Is(is[i]) {
|
||||||
|
t.Errorf("Expected node %d to be %s, found %+v", i, is[i], sel.Get(i))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func printSel(t *testing.T, sel *Selection) {
|
||||||
|
if testing.Verbose() {
|
||||||
|
h, err := sel.Html()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
t.Log(h)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func loadDoc(page string) *Document {
|
||||||
|
var f *os.File
|
||||||
|
var e error
|
||||||
|
|
||||||
|
if f, e = os.Open(fmt.Sprintf("./testdata/%s", page)); e != nil {
|
||||||
|
panic(e.Error())
|
||||||
|
}
|
||||||
|
defer f.Close()
|
||||||
|
|
||||||
|
var node *html.Node
|
||||||
|
if node, e = html.Parse(f); e != nil {
|
||||||
|
panic(e.Error())
|
||||||
|
}
|
||||||
|
return NewDocumentFromNode(node)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestNewDocument(t *testing.T) {
|
||||||
|
if f, e := os.Open("./testdata/page.html"); e != nil {
|
||||||
|
t.Error(e.Error())
|
||||||
|
} else {
|
||||||
|
defer f.Close()
|
||||||
|
if node, e := html.Parse(f); e != nil {
|
||||||
|
t.Error(e.Error())
|
||||||
|
} else {
|
||||||
|
doc = NewDocumentFromNode(node)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestNewDocumentFromReader(t *testing.T) {
|
||||||
|
cases := []struct {
|
||||||
|
src string
|
||||||
|
err bool
|
||||||
|
sel string
|
||||||
|
cnt int
|
||||||
|
}{
|
||||||
|
0: {
|
||||||
|
src: `
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>Test</title>
|
||||||
|
<body>
|
||||||
|
<h1>Hi</h1>
|
||||||
|
</body>
|
||||||
|
</html>`,
|
||||||
|
sel: "h1",
|
||||||
|
cnt: 1,
|
||||||
|
},
|
||||||
|
1: {
|
||||||
|
// Actually pretty hard to make html.Parse return an error
|
||||||
|
// based on content...
|
||||||
|
src: `<html><body><aef<eqf>>>qq></body></ht>`,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
buf := bytes.NewBuffer(nil)
|
||||||
|
|
||||||
|
for i, c := range cases {
|
||||||
|
buf.Reset()
|
||||||
|
buf.WriteString(c.src)
|
||||||
|
|
||||||
|
d, e := NewDocumentFromReader(buf)
|
||||||
|
if (e != nil) != c.err {
|
||||||
|
if c.err {
|
||||||
|
t.Errorf("[%d] - expected error, got none", i)
|
||||||
|
} else {
|
||||||
|
t.Errorf("[%d] - expected no error, got %s", i, e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if c.sel != "" {
|
||||||
|
s := d.Find(c.sel)
|
||||||
|
if s.Length() != c.cnt {
|
||||||
|
t.Errorf("[%d] - expected %d nodes, found %d", i, c.cnt, s.Length())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestNewDocumentFromResponseNil(t *testing.T) {
|
||||||
|
_, e := NewDocumentFromResponse(nil)
|
||||||
|
if e == nil {
|
||||||
|
t.Error("Expected error, got none")
|
||||||
|
}
|
||||||
|
}
|
84
Godeps/_workspace/src/github.com/PuerkitoBio/goquery/utilities.go
generated
vendored
Normal file
84
Godeps/_workspace/src/github.com/PuerkitoBio/goquery/utilities.go
generated
vendored
Normal file
|
@ -0,0 +1,84 @@
|
||||||
|
package goquery
|
||||||
|
|
||||||
|
import (
|
||||||
|
"golang.org/x/net/html"
|
||||||
|
)
|
||||||
|
|
||||||
|
func getChildren(n *html.Node) (result []*html.Node) {
|
||||||
|
for c := n.FirstChild; c != nil; c = c.NextSibling {
|
||||||
|
result = append(result, c)
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
// Loop through all container nodes to search for the target node.
|
||||||
|
func sliceContains(container []*html.Node, contained *html.Node) bool {
|
||||||
|
for _, n := range container {
|
||||||
|
if nodeContains(n, contained) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// Checks if the contained node is within the container node.
|
||||||
|
func nodeContains(container *html.Node, contained *html.Node) bool {
|
||||||
|
// Check if the parent of the contained node is the container node, traversing
|
||||||
|
// upward until the top is reached, or the container is found.
|
||||||
|
for contained = contained.Parent; contained != nil; contained = contained.Parent {
|
||||||
|
if container == contained {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// Checks if the target node is in the slice of nodes.
|
||||||
|
func isInSlice(slice []*html.Node, node *html.Node) bool {
|
||||||
|
return indexInSlice(slice, node) > -1
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns the index of the target node in the slice, or -1.
|
||||||
|
func indexInSlice(slice []*html.Node, node *html.Node) int {
|
||||||
|
if node != nil {
|
||||||
|
for i, n := range slice {
|
||||||
|
if n == node {
|
||||||
|
return i
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
|
||||||
|
// Appends the new nodes to the target slice, making sure no duplicate is added.
|
||||||
|
// There is no check to the original state of the target slice, so it may still
|
||||||
|
// contain duplicates. The target slice is returned because append() may create
|
||||||
|
// a new underlying array.
|
||||||
|
func appendWithoutDuplicates(target []*html.Node, nodes []*html.Node) []*html.Node {
|
||||||
|
for _, n := range nodes {
|
||||||
|
if !isInSlice(target, n) {
|
||||||
|
target = append(target, n)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return target
|
||||||
|
}
|
||||||
|
|
||||||
|
// Loop through a selection, returning only those nodes that pass the predicate
|
||||||
|
// function.
|
||||||
|
func grep(sel *Selection, predicate func(i int, s *Selection) bool) (result []*html.Node) {
|
||||||
|
for i, n := range sel.Nodes {
|
||||||
|
if predicate(i, newSingleSelection(n, sel.document)) {
|
||||||
|
result = append(result, n)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
// Creates a new Selection object based on the specified nodes, and keeps the
|
||||||
|
// source Selection object on the stack (linked list).
|
||||||
|
func pushStack(fromSel *Selection, nodes []*html.Node) *Selection {
|
||||||
|
result := &Selection{nodes, fromSel.document, fromSel}
|
||||||
|
return result
|
||||||
|
}
|
14
Godeps/_workspace/src/github.com/andybalholm/cascadia/.travis.yml
generated
vendored
Normal file
14
Godeps/_workspace/src/github.com/andybalholm/cascadia/.travis.yml
generated
vendored
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
language: go
|
||||||
|
|
||||||
|
go:
|
||||||
|
- 1.3
|
||||||
|
- 1.4
|
||||||
|
|
||||||
|
install:
|
||||||
|
- go get github.com/andybalholm/cascadia
|
||||||
|
|
||||||
|
script:
|
||||||
|
- go test -v
|
||||||
|
|
||||||
|
notifications:
|
||||||
|
email: false
|
24
Godeps/_workspace/src/github.com/andybalholm/cascadia/LICENSE
generated
vendored
Normal file
24
Godeps/_workspace/src/github.com/andybalholm/cascadia/LICENSE
generated
vendored
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
Copyright (c) 2011 Andy Balholm. All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions are
|
||||||
|
met:
|
||||||
|
|
||||||
|
* Redistributions of source code must retain the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer.
|
||||||
|
* Redistributions in binary form must reproduce the above
|
||||||
|
copyright notice, this list of conditions and the following disclaimer
|
||||||
|
in the documentation and/or other materials provided with the
|
||||||
|
distribution.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
5
Godeps/_workspace/src/github.com/andybalholm/cascadia/README.md
generated
vendored
Normal file
5
Godeps/_workspace/src/github.com/andybalholm/cascadia/README.md
generated
vendored
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
# cascadia
|
||||||
|
|
||||||
|
[![](https://travis-ci.org/andybalholm/cascadia.svg)](https://travis-ci.org/andybalholm/cascadia)
|
||||||
|
|
||||||
|
The Cascadia package implements CSS selectors for use with the parse trees produced by the html package.
|
53
Godeps/_workspace/src/github.com/andybalholm/cascadia/benchmark_test.go
generated
vendored
Normal file
53
Godeps/_workspace/src/github.com/andybalholm/cascadia/benchmark_test.go
generated
vendored
Normal file
|
@ -0,0 +1,53 @@
|
||||||
|
package cascadia
|
||||||
|
|
||||||
|
import (
|
||||||
|
"strings"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"golang.org/x/net/html"
|
||||||
|
)
|
||||||
|
|
||||||
|
func MustParseHTML(doc string) *html.Node {
|
||||||
|
dom, err := html.Parse(strings.NewReader(doc))
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
return dom
|
||||||
|
}
|
||||||
|
|
||||||
|
var selector = MustCompile(`div.matched`)
|
||||||
|
var doc = `<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<body>
|
||||||
|
<div class="matched">
|
||||||
|
<div>
|
||||||
|
<div class="matched"></div>
|
||||||
|
<div class="matched"></div>
|
||||||
|
<div class="matched"></div>
|
||||||
|
<div class="matched"></div>
|
||||||
|
<div class="matched"></div>
|
||||||
|
<div class="matched"></div>
|
||||||
|
<div class="matched"></div>
|
||||||
|
<div class="matched"></div>
|
||||||
|
<div class="matched"></div>
|
||||||
|
<div class="matched"></div>
|
||||||
|
<div class="matched"></div>
|
||||||
|
<div class="matched"></div>
|
||||||
|
<div class="matched"></div>
|
||||||
|
<div class="matched"></div>
|
||||||
|
<div class="matched"></div>
|
||||||
|
<div class="matched"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
`
|
||||||
|
var dom = MustParseHTML(doc)
|
||||||
|
|
||||||
|
func BenchmarkMatchAll(b *testing.B) {
|
||||||
|
var matches []*html.Node
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
matches = selector.MatchAll(dom)
|
||||||
|
}
|
||||||
|
_ = matches
|
||||||
|
}
|
815
Godeps/_workspace/src/github.com/andybalholm/cascadia/parser.go
generated
vendored
Normal file
815
Godeps/_workspace/src/github.com/andybalholm/cascadia/parser.go
generated
vendored
Normal file
|
@ -0,0 +1,815 @@
|
||||||
|
// The cascadia package is an implementation of CSS selectors.
|
||||||
|
package cascadia
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"regexp"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"golang.org/x/net/html"
|
||||||
|
)
|
||||||
|
|
||||||
|
// a parser for CSS selectors
|
||||||
|
type parser struct {
|
||||||
|
s string // the source text
|
||||||
|
i int // the current position
|
||||||
|
}
|
||||||
|
|
||||||
|
// parseEscape parses a backslash escape.
|
||||||
|
func (p *parser) parseEscape() (result string, err error) {
|
||||||
|
if len(p.s) < p.i+2 || p.s[p.i] != '\\' {
|
||||||
|
return "", errors.New("invalid escape sequence")
|
||||||
|
}
|
||||||
|
|
||||||
|
start := p.i + 1
|
||||||
|
c := p.s[start]
|
||||||
|
switch {
|
||||||
|
case c == '\r' || c == '\n' || c == '\f':
|
||||||
|
return "", errors.New("escaped line ending outside string")
|
||||||
|
case hexDigit(c):
|
||||||
|
// unicode escape (hex)
|
||||||
|
var i int
|
||||||
|
for i = start; i < p.i+6 && i < len(p.s) && hexDigit(p.s[i]); i++ {
|
||||||
|
// empty
|
||||||
|
}
|
||||||
|
v, _ := strconv.ParseUint(p.s[start:i], 16, 21)
|
||||||
|
if len(p.s) > i {
|
||||||
|
switch p.s[i] {
|
||||||
|
case '\r':
|
||||||
|
i++
|
||||||
|
if len(p.s) > i && p.s[i] == '\n' {
|
||||||
|
i++
|
||||||
|
}
|
||||||
|
case ' ', '\t', '\n', '\f':
|
||||||
|
i++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
p.i = i
|
||||||
|
return string(rune(v)), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return the literal character after the backslash.
|
||||||
|
result = p.s[start : start+1]
|
||||||
|
p.i += 2
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func hexDigit(c byte) bool {
|
||||||
|
return '0' <= c && c <= '9' || 'a' <= c && c <= 'f' || 'A' <= c && c <= 'F'
|
||||||
|
}
|
||||||
|
|
||||||
|
// nameStart returns whether c can be the first character of an identifier
|
||||||
|
// (not counting an initial hyphen, or an escape sequence).
|
||||||
|
func nameStart(c byte) bool {
|
||||||
|
return 'a' <= c && c <= 'z' || 'A' <= c && c <= 'Z' || c == '_' || c > 127
|
||||||
|
}
|
||||||
|
|
||||||
|
// nameChar returns whether c can be a character within an identifier
|
||||||
|
// (not counting an escape sequence).
|
||||||
|
func nameChar(c byte) bool {
|
||||||
|
return 'a' <= c && c <= 'z' || 'A' <= c && c <= 'Z' || c == '_' || c > 127 ||
|
||||||
|
c == '-' || '0' <= c && c <= '9'
|
||||||
|
}
|
||||||
|
|
||||||
|
// parseIdentifier parses an identifier.
|
||||||
|
func (p *parser) parseIdentifier() (result string, err error) {
|
||||||
|
startingDash := false
|
||||||
|
if len(p.s) > p.i && p.s[p.i] == '-' {
|
||||||
|
startingDash = true
|
||||||
|
p.i++
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(p.s) <= p.i {
|
||||||
|
return "", errors.New("expected identifier, found EOF instead")
|
||||||
|
}
|
||||||
|
|
||||||
|
if c := p.s[p.i]; !(nameStart(c) || c == '\\') {
|
||||||
|
return "", fmt.Errorf("expected identifier, found %c instead", c)
|
||||||
|
}
|
||||||
|
|
||||||
|
result, err = p.parseName()
|
||||||
|
if startingDash && err == nil {
|
||||||
|
result = "-" + result
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// parseName parses a name (which is like an identifier, but doesn't have
|
||||||
|
// extra restrictions on the first character).
|
||||||
|
func (p *parser) parseName() (result string, err error) {
|
||||||
|
i := p.i
|
||||||
|
loop:
|
||||||
|
for i < len(p.s) {
|
||||||
|
c := p.s[i]
|
||||||
|
switch {
|
||||||
|
case nameChar(c):
|
||||||
|
start := i
|
||||||
|
for i < len(p.s) && nameChar(p.s[i]) {
|
||||||
|
i++
|
||||||
|
}
|
||||||
|
result += p.s[start:i]
|
||||||
|
case c == '\\':
|
||||||
|
p.i = i
|
||||||
|
val, err := p.parseEscape()
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
i = p.i
|
||||||
|
result += val
|
||||||
|
default:
|
||||||
|
break loop
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if result == "" {
|
||||||
|
return "", errors.New("expected name, found EOF instead")
|
||||||
|
}
|
||||||
|
|
||||||
|
p.i = i
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// parseString parses a single- or double-quoted string.
|
||||||
|
func (p *parser) parseString() (result string, err error) {
|
||||||
|
i := p.i
|
||||||
|
if len(p.s) < i+2 {
|
||||||
|
return "", errors.New("expected string, found EOF instead")
|
||||||
|
}
|
||||||
|
|
||||||
|
quote := p.s[i]
|
||||||
|
i++
|
||||||
|
|
||||||
|
loop:
|
||||||
|
for i < len(p.s) {
|
||||||
|
switch p.s[i] {
|
||||||
|
case '\\':
|
||||||
|
if len(p.s) > i+1 {
|
||||||
|
switch c := p.s[i+1]; c {
|
||||||
|
case '\r':
|
||||||
|
if len(p.s) > i+2 && p.s[i+2] == '\n' {
|
||||||
|
i += 3
|
||||||
|
continue loop
|
||||||
|
}
|
||||||
|
fallthrough
|
||||||
|
case '\n', '\f':
|
||||||
|
i += 2
|
||||||
|
continue loop
|
||||||
|
}
|
||||||
|
}
|
||||||
|
p.i = i
|
||||||
|
val, err := p.parseEscape()
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
i = p.i
|
||||||
|
result += val
|
||||||
|
case quote:
|
||||||
|
break loop
|
||||||
|
case '\r', '\n', '\f':
|
||||||
|
return "", errors.New("unexpected end of line in string")
|
||||||
|
default:
|
||||||
|
start := i
|
||||||
|
for i < len(p.s) {
|
||||||
|
if c := p.s[i]; c == quote || c == '\\' || c == '\r' || c == '\n' || c == '\f' {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
i++
|
||||||
|
}
|
||||||
|
result += p.s[start:i]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if i >= len(p.s) {
|
||||||
|
return "", errors.New("EOF in string")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Consume the final quote.
|
||||||
|
i++
|
||||||
|
|
||||||
|
p.i = i
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// parseRegex parses a regular expression; the end is defined by encountering an
|
||||||
|
// unmatched closing ')' or ']' which is not consumed
|
||||||
|
func (p *parser) parseRegex() (rx *regexp.Regexp, err error) {
|
||||||
|
i := p.i
|
||||||
|
if len(p.s) < i+2 {
|
||||||
|
return nil, errors.New("expected regular expression, found EOF instead")
|
||||||
|
}
|
||||||
|
|
||||||
|
// number of open parens or brackets;
|
||||||
|
// when it becomes negative, finished parsing regex
|
||||||
|
open := 0
|
||||||
|
|
||||||
|
loop:
|
||||||
|
for i < len(p.s) {
|
||||||
|
switch p.s[i] {
|
||||||
|
case '(', '[':
|
||||||
|
open++
|
||||||
|
case ')', ']':
|
||||||
|
open--
|
||||||
|
if open < 0 {
|
||||||
|
break loop
|
||||||
|
}
|
||||||
|
}
|
||||||
|
i++
|
||||||
|
}
|
||||||
|
|
||||||
|
if i >= len(p.s) {
|
||||||
|
return nil, errors.New("EOF in regular expression")
|
||||||
|
}
|
||||||
|
rx, err = regexp.Compile(p.s[p.i:i])
|
||||||
|
p.i = i
|
||||||
|
return rx, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// skipWhitespace consumes whitespace characters and comments.
|
||||||
|
// It returns true if there was actually anything to skip.
|
||||||
|
func (p *parser) skipWhitespace() bool {
|
||||||
|
i := p.i
|
||||||
|
for i < len(p.s) {
|
||||||
|
switch p.s[i] {
|
||||||
|
case ' ', '\t', '\r', '\n', '\f':
|
||||||
|
i++
|
||||||
|
continue
|
||||||
|
case '/':
|
||||||
|
if strings.HasPrefix(p.s[i:], "/*") {
|
||||||
|
end := strings.Index(p.s[i+len("/*"):], "*/")
|
||||||
|
if end != -1 {
|
||||||
|
i += end + len("/**/")
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
if i > p.i {
|
||||||
|
p.i = i
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// consumeParenthesis consumes an opening parenthesis and any following
|
||||||
|
// whitespace. It returns true if there was actually a parenthesis to skip.
|
||||||
|
func (p *parser) consumeParenthesis() bool {
|
||||||
|
if p.i < len(p.s) && p.s[p.i] == '(' {
|
||||||
|
p.i++
|
||||||
|
p.skipWhitespace()
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// consumeClosingParenthesis consumes a closing parenthesis and any preceding
|
||||||
|
// whitespace. It returns true if there was actually a parenthesis to skip.
|
||||||
|
func (p *parser) consumeClosingParenthesis() bool {
|
||||||
|
i := p.i
|
||||||
|
p.skipWhitespace()
|
||||||
|
if p.i < len(p.s) && p.s[p.i] == ')' {
|
||||||
|
p.i++
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
p.i = i
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// parseTypeSelector parses a type selector (one that matches by tag name).
|
||||||
|
func (p *parser) parseTypeSelector() (result Selector, err error) {
|
||||||
|
tag, err := p.parseIdentifier()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return typeSelector(tag), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// parseIDSelector parses a selector that matches by id attribute.
|
||||||
|
func (p *parser) parseIDSelector() (Selector, error) {
|
||||||
|
if p.i >= len(p.s) {
|
||||||
|
return nil, fmt.Errorf("expected id selector (#id), found EOF instead")
|
||||||
|
}
|
||||||
|
if p.s[p.i] != '#' {
|
||||||
|
return nil, fmt.Errorf("expected id selector (#id), found '%c' instead", p.s[p.i])
|
||||||
|
}
|
||||||
|
|
||||||
|
p.i++
|
||||||
|
id, err := p.parseName()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return attributeEqualsSelector("id", id), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// parseClassSelector parses a selector that matches by class attribute.
|
||||||
|
func (p *parser) parseClassSelector() (Selector, error) {
|
||||||
|
if p.i >= len(p.s) {
|
||||||
|
return nil, fmt.Errorf("expected class selector (.class), found EOF instead")
|
||||||
|
}
|
||||||
|
if p.s[p.i] != '.' {
|
||||||
|
return nil, fmt.Errorf("expected class selector (.class), found '%c' instead", p.s[p.i])
|
||||||
|
}
|
||||||
|
|
||||||
|
p.i++
|
||||||
|
class, err := p.parseIdentifier()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return attributeIncludesSelector("class", class), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// parseAttributeSelector parses a selector that matches by attribute value.
|
||||||
|
func (p *parser) parseAttributeSelector() (Selector, error) {
|
||||||
|
if p.i >= len(p.s) {
|
||||||
|
return nil, fmt.Errorf("expected attribute selector ([attribute]), found EOF instead")
|
||||||
|
}
|
||||||
|
if p.s[p.i] != '[' {
|
||||||
|
return nil, fmt.Errorf("expected attribute selector ([attribute]), found '%c' instead", p.s[p.i])
|
||||||
|
}
|
||||||
|
|
||||||
|
p.i++
|
||||||
|
p.skipWhitespace()
|
||||||
|
key, err := p.parseIdentifier()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
p.skipWhitespace()
|
||||||
|
if p.i >= len(p.s) {
|
||||||
|
return nil, errors.New("unexpected EOF in attribute selector")
|
||||||
|
}
|
||||||
|
|
||||||
|
if p.s[p.i] == ']' {
|
||||||
|
p.i++
|
||||||
|
return attributeExistsSelector(key), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if p.i+2 >= len(p.s) {
|
||||||
|
return nil, errors.New("unexpected EOF in attribute selector")
|
||||||
|
}
|
||||||
|
|
||||||
|
op := p.s[p.i : p.i+2]
|
||||||
|
if op[0] == '=' {
|
||||||
|
op = "="
|
||||||
|
} else if op[1] != '=' {
|
||||||
|
return nil, fmt.Errorf(`expected equality operator, found "%s" instead`, op)
|
||||||
|
}
|
||||||
|
p.i += len(op)
|
||||||
|
|
||||||
|
p.skipWhitespace()
|
||||||
|
if p.i >= len(p.s) {
|
||||||
|
return nil, errors.New("unexpected EOF in attribute selector")
|
||||||
|
}
|
||||||
|
var val string
|
||||||
|
var rx *regexp.Regexp
|
||||||
|
if op == "#=" {
|
||||||
|
rx, err = p.parseRegex()
|
||||||
|
} else {
|
||||||
|
switch p.s[p.i] {
|
||||||
|
case '\'', '"':
|
||||||
|
val, err = p.parseString()
|
||||||
|
default:
|
||||||
|
val, err = p.parseIdentifier()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
p.skipWhitespace()
|
||||||
|
if p.i >= len(p.s) {
|
||||||
|
return nil, errors.New("unexpected EOF in attribute selector")
|
||||||
|
}
|
||||||
|
if p.s[p.i] != ']' {
|
||||||
|
return nil, fmt.Errorf("expected ']', found '%c' instead", p.s[p.i])
|
||||||
|
}
|
||||||
|
p.i++
|
||||||
|
|
||||||
|
switch op {
|
||||||
|
case "=":
|
||||||
|
return attributeEqualsSelector(key, val), nil
|
||||||
|
case "~=":
|
||||||
|
return attributeIncludesSelector(key, val), nil
|
||||||
|
case "|=":
|
||||||
|
return attributeDashmatchSelector(key, val), nil
|
||||||
|
case "^=":
|
||||||
|
return attributePrefixSelector(key, val), nil
|
||||||
|
case "$=":
|
||||||
|
return attributeSuffixSelector(key, val), nil
|
||||||
|
case "*=":
|
||||||
|
return attributeSubstringSelector(key, val), nil
|
||||||
|
case "#=":
|
||||||
|
return attributeRegexSelector(key, rx), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil, fmt.Errorf("attribute operator %q is not supported", op)
|
||||||
|
}
|
||||||
|
|
||||||
|
var expectedParenthesis = errors.New("expected '(' but didn't find it")
|
||||||
|
var expectedClosingParenthesis = errors.New("expected ')' but didn't find it")
|
||||||
|
|
||||||
|
// parsePseudoclassSelector parses a pseudoclass selector like :not(p).
|
||||||
|
func (p *parser) parsePseudoclassSelector() (Selector, error) {
|
||||||
|
if p.i >= len(p.s) {
|
||||||
|
return nil, fmt.Errorf("expected pseudoclass selector (:pseudoclass), found EOF instead")
|
||||||
|
}
|
||||||
|
if p.s[p.i] != ':' {
|
||||||
|
return nil, fmt.Errorf("expected attribute selector (:pseudoclass), found '%c' instead", p.s[p.i])
|
||||||
|
}
|
||||||
|
|
||||||
|
p.i++
|
||||||
|
name, err := p.parseIdentifier()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
name = toLowerASCII(name)
|
||||||
|
|
||||||
|
switch name {
|
||||||
|
case "not", "has", "haschild":
|
||||||
|
if !p.consumeParenthesis() {
|
||||||
|
return nil, expectedParenthesis
|
||||||
|
}
|
||||||
|
sel, err := p.parseSelectorGroup()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if !p.consumeClosingParenthesis() {
|
||||||
|
return nil, expectedClosingParenthesis
|
||||||
|
}
|
||||||
|
|
||||||
|
switch name {
|
||||||
|
case "not":
|
||||||
|
return negatedSelector(sel), nil
|
||||||
|
case "has":
|
||||||
|
return hasDescendantSelector(sel), nil
|
||||||
|
case "haschild":
|
||||||
|
return hasChildSelector(sel), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
case "contains", "containsown":
|
||||||
|
if !p.consumeParenthesis() {
|
||||||
|
return nil, expectedParenthesis
|
||||||
|
}
|
||||||
|
var val string
|
||||||
|
switch p.s[p.i] {
|
||||||
|
case '\'', '"':
|
||||||
|
val, err = p.parseString()
|
||||||
|
default:
|
||||||
|
val, err = p.parseIdentifier()
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
val = strings.ToLower(val)
|
||||||
|
p.skipWhitespace()
|
||||||
|
if p.i >= len(p.s) {
|
||||||
|
return nil, errors.New("unexpected EOF in pseudo selector")
|
||||||
|
}
|
||||||
|
if !p.consumeClosingParenthesis() {
|
||||||
|
return nil, expectedClosingParenthesis
|
||||||
|
}
|
||||||
|
|
||||||
|
switch name {
|
||||||
|
case "contains":
|
||||||
|
return textSubstrSelector(val), nil
|
||||||
|
case "containsown":
|
||||||
|
return ownTextSubstrSelector(val), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
case "matches", "matchesown":
|
||||||
|
if !p.consumeParenthesis() {
|
||||||
|
return nil, expectedParenthesis
|
||||||
|
}
|
||||||
|
rx, err := p.parseRegex()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if p.i >= len(p.s) {
|
||||||
|
return nil, errors.New("unexpected EOF in pseudo selector")
|
||||||
|
}
|
||||||
|
if !p.consumeClosingParenthesis() {
|
||||||
|
return nil, expectedClosingParenthesis
|
||||||
|
}
|
||||||
|
|
||||||
|
switch name {
|
||||||
|
case "matches":
|
||||||
|
return textRegexSelector(rx), nil
|
||||||
|
case "matchesown":
|
||||||
|
return ownTextRegexSelector(rx), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
case "nth-child", "nth-last-child", "nth-of-type", "nth-last-of-type":
|
||||||
|
if !p.consumeParenthesis() {
|
||||||
|
return nil, expectedParenthesis
|
||||||
|
}
|
||||||
|
a, b, err := p.parseNth()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if !p.consumeClosingParenthesis() {
|
||||||
|
return nil, expectedClosingParenthesis
|
||||||
|
}
|
||||||
|
return nthChildSelector(a, b,
|
||||||
|
name == "nth-last-child" || name == "nth-last-of-type",
|
||||||
|
name == "nth-of-type" || name == "nth-last-of-type"),
|
||||||
|
nil
|
||||||
|
|
||||||
|
case "first-child":
|
||||||
|
return nthChildSelector(0, 1, false, false), nil
|
||||||
|
case "last-child":
|
||||||
|
return nthChildSelector(0, 1, true, false), nil
|
||||||
|
case "first-of-type":
|
||||||
|
return nthChildSelector(0, 1, false, true), nil
|
||||||
|
case "last-of-type":
|
||||||
|
return nthChildSelector(0, 1, true, true), nil
|
||||||
|
case "only-child":
|
||||||
|
return onlyChildSelector(false), nil
|
||||||
|
case "only-of-type":
|
||||||
|
return onlyChildSelector(true), nil
|
||||||
|
case "input":
|
||||||
|
return inputSelector, nil
|
||||||
|
case "empty":
|
||||||
|
return emptyElementSelector, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil, fmt.Errorf("unknown pseudoclass :%s", name)
|
||||||
|
}
|
||||||
|
|
||||||
|
// parseInteger parses a decimal integer.
|
||||||
|
func (p *parser) parseInteger() (int, error) {
|
||||||
|
i := p.i
|
||||||
|
start := i
|
||||||
|
for i < len(p.s) && '0' <= p.s[i] && p.s[i] <= '9' {
|
||||||
|
i++
|
||||||
|
}
|
||||||
|
if i == start {
|
||||||
|
return 0, errors.New("expected integer, but didn't find it.")
|
||||||
|
}
|
||||||
|
p.i = i
|
||||||
|
|
||||||
|
val, err := strconv.Atoi(p.s[start:i])
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return val, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// parseNth parses the argument for :nth-child (normally of the form an+b).
|
||||||
|
func (p *parser) parseNth() (a, b int, err error) {
|
||||||
|
// initial state
|
||||||
|
if p.i >= len(p.s) {
|
||||||
|
goto eof
|
||||||
|
}
|
||||||
|
switch p.s[p.i] {
|
||||||
|
case '-':
|
||||||
|
p.i++
|
||||||
|
goto negativeA
|
||||||
|
case '+':
|
||||||
|
p.i++
|
||||||
|
goto positiveA
|
||||||
|
case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
|
||||||
|
goto positiveA
|
||||||
|
case 'n', 'N':
|
||||||
|
a = 1
|
||||||
|
p.i++
|
||||||
|
goto readN
|
||||||
|
case 'o', 'O', 'e', 'E':
|
||||||
|
id, err := p.parseName()
|
||||||
|
if err != nil {
|
||||||
|
return 0, 0, err
|
||||||
|
}
|
||||||
|
id = toLowerASCII(id)
|
||||||
|
if id == "odd" {
|
||||||
|
return 2, 1, nil
|
||||||
|
}
|
||||||
|
if id == "even" {
|
||||||
|
return 2, 0, nil
|
||||||
|
}
|
||||||
|
return 0, 0, fmt.Errorf("expected 'odd' or 'even', but found '%s' instead", id)
|
||||||
|
default:
|
||||||
|
goto invalid
|
||||||
|
}
|
||||||
|
|
||||||
|
positiveA:
|
||||||
|
if p.i >= len(p.s) {
|
||||||
|
goto eof
|
||||||
|
}
|
||||||
|
switch p.s[p.i] {
|
||||||
|
case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
|
||||||
|
a, err = p.parseInteger()
|
||||||
|
if err != nil {
|
||||||
|
return 0, 0, err
|
||||||
|
}
|
||||||
|
goto readA
|
||||||
|
case 'n', 'N':
|
||||||
|
a = 1
|
||||||
|
p.i++
|
||||||
|
goto readN
|
||||||
|
default:
|
||||||
|
goto invalid
|
||||||
|
}
|
||||||
|
|
||||||
|
negativeA:
|
||||||
|
if p.i >= len(p.s) {
|
||||||
|
goto eof
|
||||||
|
}
|
||||||
|
switch p.s[p.i] {
|
||||||
|
case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
|
||||||
|
a, err = p.parseInteger()
|
||||||
|
if err != nil {
|
||||||
|
return 0, 0, err
|
||||||
|
}
|
||||||
|
a = -a
|
||||||
|
goto readA
|
||||||
|
case 'n', 'N':
|
||||||
|
a = -1
|
||||||
|
p.i++
|
||||||
|
goto readN
|
||||||
|
default:
|
||||||
|
goto invalid
|
||||||
|
}
|
||||||
|
|
||||||
|
readA:
|
||||||
|
if p.i >= len(p.s) {
|
||||||
|
goto eof
|
||||||
|
}
|
||||||
|
switch p.s[p.i] {
|
||||||
|
case 'n', 'N':
|
||||||
|
p.i++
|
||||||
|
goto readN
|
||||||
|
default:
|
||||||
|
// The number we read as a is actually b.
|
||||||
|
return 0, a, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
readN:
|
||||||
|
p.skipWhitespace()
|
||||||
|
if p.i >= len(p.s) {
|
||||||
|
goto eof
|
||||||
|
}
|
||||||
|
switch p.s[p.i] {
|
||||||
|
case '+':
|
||||||
|
p.i++
|
||||||
|
p.skipWhitespace()
|
||||||
|
b, err = p.parseInteger()
|
||||||
|
if err != nil {
|
||||||
|
return 0, 0, err
|
||||||
|
}
|
||||||
|
return a, b, nil
|
||||||
|
case '-':
|
||||||
|
p.i++
|
||||||
|
p.skipWhitespace()
|
||||||
|
b, err = p.parseInteger()
|
||||||
|
if err != nil {
|
||||||
|
return 0, 0, err
|
||||||
|
}
|
||||||
|
return a, -b, nil
|
||||||
|
default:
|
||||||
|
return a, 0, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
eof:
|
||||||
|
return 0, 0, errors.New("unexpected EOF while attempting to parse expression of form an+b")
|
||||||
|
|
||||||
|
invalid:
|
||||||
|
return 0, 0, errors.New("unexpected character while attempting to parse expression of form an+b")
|
||||||
|
}
|
||||||
|
|
||||||
|
// parseSimpleSelectorSequence parses a selector sequence that applies to
|
||||||
|
// a single element.
|
||||||
|
func (p *parser) parseSimpleSelectorSequence() (Selector, error) {
|
||||||
|
var result Selector
|
||||||
|
|
||||||
|
if p.i >= len(p.s) {
|
||||||
|
return nil, errors.New("expected selector, found EOF instead")
|
||||||
|
}
|
||||||
|
|
||||||
|
switch p.s[p.i] {
|
||||||
|
case '*':
|
||||||
|
// It's the universal selector. Just skip over it, since it doesn't affect the meaning.
|
||||||
|
p.i++
|
||||||
|
case '#', '.', '[', ':':
|
||||||
|
// There's no type selector. Wait to process the other till the main loop.
|
||||||
|
default:
|
||||||
|
r, err := p.parseTypeSelector()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
result = r
|
||||||
|
}
|
||||||
|
|
||||||
|
loop:
|
||||||
|
for p.i < len(p.s) {
|
||||||
|
var ns Selector
|
||||||
|
var err error
|
||||||
|
switch p.s[p.i] {
|
||||||
|
case '#':
|
||||||
|
ns, err = p.parseIDSelector()
|
||||||
|
case '.':
|
||||||
|
ns, err = p.parseClassSelector()
|
||||||
|
case '[':
|
||||||
|
ns, err = p.parseAttributeSelector()
|
||||||
|
case ':':
|
||||||
|
ns, err = p.parsePseudoclassSelector()
|
||||||
|
default:
|
||||||
|
break loop
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if result == nil {
|
||||||
|
result = ns
|
||||||
|
} else {
|
||||||
|
result = intersectionSelector(result, ns)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if result == nil {
|
||||||
|
result = func(n *html.Node) bool {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// parseSelector parses a selector that may include combinators.
|
||||||
|
func (p *parser) parseSelector() (result Selector, err error) {
|
||||||
|
p.skipWhitespace()
|
||||||
|
result, err = p.parseSimpleSelectorSequence()
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
for {
|
||||||
|
var combinator byte
|
||||||
|
if p.skipWhitespace() {
|
||||||
|
combinator = ' '
|
||||||
|
}
|
||||||
|
if p.i >= len(p.s) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
switch p.s[p.i] {
|
||||||
|
case '+', '>', '~':
|
||||||
|
combinator = p.s[p.i]
|
||||||
|
p.i++
|
||||||
|
p.skipWhitespace()
|
||||||
|
case ',', ')':
|
||||||
|
// These characters can't begin a selector, but they can legally occur after one.
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if combinator == 0 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
c, err := p.parseSimpleSelectorSequence()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
switch combinator {
|
||||||
|
case ' ':
|
||||||
|
result = descendantSelector(result, c)
|
||||||
|
case '>':
|
||||||
|
result = childSelector(result, c)
|
||||||
|
case '+':
|
||||||
|
result = siblingSelector(result, c, true)
|
||||||
|
case '~':
|
||||||
|
result = siblingSelector(result, c, false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
panic("unreachable")
|
||||||
|
}
|
||||||
|
|
||||||
|
// parseSelectorGroup parses a group of selectors, separated by commas.
|
||||||
|
func (p *parser) parseSelectorGroup() (result Selector, err error) {
|
||||||
|
result, err = p.parseSelector()
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
for p.i < len(p.s) {
|
||||||
|
if p.s[p.i] != ',' {
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
p.i++
|
||||||
|
c, err := p.parseSelector()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
result = unionSelector(result, c)
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
86
Godeps/_workspace/src/github.com/andybalholm/cascadia/parser_test.go
generated
vendored
Normal file
86
Godeps/_workspace/src/github.com/andybalholm/cascadia/parser_test.go
generated
vendored
Normal file
|
@ -0,0 +1,86 @@
|
||||||
|
package cascadia
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
var identifierTests = map[string]string{
|
||||||
|
"x": "x",
|
||||||
|
"96": "",
|
||||||
|
"-x": "-x",
|
||||||
|
`r\e9 sumé`: "résumé",
|
||||||
|
`a\"b`: `a"b`,
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestParseIdentifier(t *testing.T) {
|
||||||
|
for source, want := range identifierTests {
|
||||||
|
p := &parser{s: source}
|
||||||
|
got, err := p.parseIdentifier()
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
if want == "" {
|
||||||
|
// It was supposed to be an error.
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
t.Errorf("parsing %q: got error (%s), want %q", source, err, want)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if want == "" {
|
||||||
|
if err == nil {
|
||||||
|
t.Errorf("parsing %q: got %q, want error", source, got)
|
||||||
|
}
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if p.i < len(source) {
|
||||||
|
t.Errorf("parsing %q: %d bytes left over", source, len(source)-p.i)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if got != want {
|
||||||
|
t.Errorf("parsing %q: got %q, want %q", source, got, want)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var stringTests = map[string]string{
|
||||||
|
`"x"`: "x",
|
||||||
|
`'x'`: "x",
|
||||||
|
`'x`: "",
|
||||||
|
"'x\\\r\nx'": "xx",
|
||||||
|
`"r\e9 sumé"`: "résumé",
|
||||||
|
`"a\"b"`: `a"b`,
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestParseString(t *testing.T) {
|
||||||
|
for source, want := range stringTests {
|
||||||
|
p := &parser{s: source}
|
||||||
|
got, err := p.parseString()
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
if want == "" {
|
||||||
|
// It was supposed to be an error.
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
t.Errorf("parsing %q: got error (%s), want %q", source, err, want)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if want == "" {
|
||||||
|
if err == nil {
|
||||||
|
t.Errorf("parsing %q: got %q, want error", source, got)
|
||||||
|
}
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if p.i < len(source) {
|
||||||
|
t.Errorf("parsing %q: %d bytes left over", source, len(source)-p.i)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if got != want {
|
||||||
|
t.Errorf("parsing %q: got %q, want %q", source, got, want)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
508
Godeps/_workspace/src/github.com/andybalholm/cascadia/selector.go
generated
vendored
Normal file
508
Godeps/_workspace/src/github.com/andybalholm/cascadia/selector.go
generated
vendored
Normal file
|
@ -0,0 +1,508 @@
|
||||||
|
package cascadia
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"fmt"
|
||||||
|
"regexp"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"golang.org/x/net/html"
|
||||||
|
)
|
||||||
|
|
||||||
|
// the Selector type, and functions for creating them
|
||||||
|
|
||||||
|
// A Selector is a function which tells whether a node matches or not.
|
||||||
|
type Selector func(*html.Node) bool
|
||||||
|
|
||||||
|
// hasChildMatch returns whether n has any child that matches a.
|
||||||
|
func hasChildMatch(n *html.Node, a Selector) bool {
|
||||||
|
for c := n.FirstChild; c != nil; c = c.NextSibling {
|
||||||
|
if a(c) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// hasDescendantMatch performs a depth-first search of n's descendants,
|
||||||
|
// testing whether any of them match a. It returns true as soon as a match is
|
||||||
|
// found, or false if no match is found.
|
||||||
|
func hasDescendantMatch(n *html.Node, a Selector) bool {
|
||||||
|
for c := n.FirstChild; c != nil; c = c.NextSibling {
|
||||||
|
if a(c) || (c.Type == html.ElementNode && hasDescendantMatch(c, a)) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// Compile parses a selector and returns, if successful, a Selector object
|
||||||
|
// that can be used to match against html.Node objects.
|
||||||
|
func Compile(sel string) (Selector, error) {
|
||||||
|
p := &parser{s: sel}
|
||||||
|
compiled, err := p.parseSelectorGroup()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if p.i < len(sel) {
|
||||||
|
return nil, fmt.Errorf("parsing %q: %d bytes left over", sel, len(sel)-p.i)
|
||||||
|
}
|
||||||
|
|
||||||
|
return compiled, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// MustCompile is like Compile, but panics instead of returning an error.
|
||||||
|
func MustCompile(sel string) Selector {
|
||||||
|
compiled, err := Compile(sel)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
return compiled
|
||||||
|
}
|
||||||
|
|
||||||
|
// MatchAll returns a slice of the nodes that match the selector,
|
||||||
|
// from n and its children.
|
||||||
|
func (s Selector) MatchAll(n *html.Node) []*html.Node {
|
||||||
|
return s.matchAllInto(n, nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s Selector) matchAllInto(n *html.Node, storage []*html.Node) []*html.Node {
|
||||||
|
if s(n) {
|
||||||
|
storage = append(storage, n)
|
||||||
|
}
|
||||||
|
|
||||||
|
for child := n.FirstChild; child != nil; child = child.NextSibling {
|
||||||
|
storage = s.matchAllInto(child, storage)
|
||||||
|
}
|
||||||
|
|
||||||
|
return storage
|
||||||
|
}
|
||||||
|
|
||||||
|
// Match returns true if the node matches the selector.
|
||||||
|
func (s Selector) Match(n *html.Node) bool {
|
||||||
|
return s(n)
|
||||||
|
}
|
||||||
|
|
||||||
|
// MatchFirst returns the first node that matches s, from n and its children.
|
||||||
|
func (s Selector) MatchFirst(n *html.Node) *html.Node {
|
||||||
|
if s.Match(n) {
|
||||||
|
return n
|
||||||
|
}
|
||||||
|
|
||||||
|
for c := n.FirstChild; c != nil; c = c.NextSibling {
|
||||||
|
m := s.MatchFirst(c)
|
||||||
|
if m != nil {
|
||||||
|
return m
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Filter returns the nodes in nodes that match the selector.
|
||||||
|
func (s Selector) Filter(nodes []*html.Node) (result []*html.Node) {
|
||||||
|
for _, n := range nodes {
|
||||||
|
if s(n) {
|
||||||
|
result = append(result, n)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
// typeSelector returns a Selector that matches elements with a given tag name.
|
||||||
|
func typeSelector(tag string) Selector {
|
||||||
|
tag = toLowerASCII(tag)
|
||||||
|
return func(n *html.Node) bool {
|
||||||
|
return n.Type == html.ElementNode && n.Data == tag
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// toLowerASCII returns s with all ASCII capital letters lowercased.
|
||||||
|
func toLowerASCII(s string) string {
|
||||||
|
var b []byte
|
||||||
|
for i := 0; i < len(s); i++ {
|
||||||
|
if c := s[i]; 'A' <= c && c <= 'Z' {
|
||||||
|
if b == nil {
|
||||||
|
b = make([]byte, len(s))
|
||||||
|
copy(b, s)
|
||||||
|
}
|
||||||
|
b[i] = s[i] + ('a' - 'A')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if b == nil {
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
|
||||||
|
return string(b)
|
||||||
|
}
|
||||||
|
|
||||||
|
// attributeSelector returns a Selector that matches elements
|
||||||
|
// where the attribute named key satisifes the function f.
|
||||||
|
func attributeSelector(key string, f func(string) bool) Selector {
|
||||||
|
key = toLowerASCII(key)
|
||||||
|
return func(n *html.Node) bool {
|
||||||
|
if n.Type != html.ElementNode {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
for _, a := range n.Attr {
|
||||||
|
if a.Key == key && f(a.Val) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// attributeExistsSelector returns a Selector that matches elements that have
|
||||||
|
// an attribute named key.
|
||||||
|
func attributeExistsSelector(key string) Selector {
|
||||||
|
return attributeSelector(key, func(string) bool { return true })
|
||||||
|
}
|
||||||
|
|
||||||
|
// attributeEqualsSelector returns a Selector that matches elements where
|
||||||
|
// the attribute named key has the value val.
|
||||||
|
func attributeEqualsSelector(key, val string) Selector {
|
||||||
|
return attributeSelector(key,
|
||||||
|
func(s string) bool {
|
||||||
|
return s == val
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// attributeIncludesSelector returns a Selector that matches elements where
|
||||||
|
// the attribute named key is a whitespace-separated list that includes val.
|
||||||
|
func attributeIncludesSelector(key, val string) Selector {
|
||||||
|
return attributeSelector(key,
|
||||||
|
func(s string) bool {
|
||||||
|
for s != "" {
|
||||||
|
i := strings.IndexAny(s, " \t\r\n\f")
|
||||||
|
if i == -1 {
|
||||||
|
return s == val
|
||||||
|
}
|
||||||
|
if s[:i] == val {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
s = s[i+1:]
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// attributeDashmatchSelector returns a Selector that matches elements where
|
||||||
|
// the attribute named key equals val or starts with val plus a hyphen.
|
||||||
|
func attributeDashmatchSelector(key, val string) Selector {
|
||||||
|
return attributeSelector(key,
|
||||||
|
func(s string) bool {
|
||||||
|
if s == val {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
if len(s) <= len(val) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if s[:len(val)] == val && s[len(val)] == '-' {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// attributePrefixSelector returns a Selector that matches elements where
|
||||||
|
// the attribute named key starts with val.
|
||||||
|
func attributePrefixSelector(key, val string) Selector {
|
||||||
|
return attributeSelector(key,
|
||||||
|
func(s string) bool {
|
||||||
|
return strings.HasPrefix(s, val)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// attributeSuffixSelector returns a Selector that matches elements where
|
||||||
|
// the attribute named key ends with val.
|
||||||
|
func attributeSuffixSelector(key, val string) Selector {
|
||||||
|
return attributeSelector(key,
|
||||||
|
func(s string) bool {
|
||||||
|
return strings.HasSuffix(s, val)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// attributeSubstringSelector returns a Selector that matches nodes where
|
||||||
|
// the attribute named key contains val.
|
||||||
|
func attributeSubstringSelector(key, val string) Selector {
|
||||||
|
return attributeSelector(key,
|
||||||
|
func(s string) bool {
|
||||||
|
return strings.Contains(s, val)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// attributeRegexSelector returns a Selector that matches nodes where
|
||||||
|
// the attribute named key matches the regular expression rx
|
||||||
|
func attributeRegexSelector(key string, rx *regexp.Regexp) Selector {
|
||||||
|
return attributeSelector(key,
|
||||||
|
func(s string) bool {
|
||||||
|
return rx.MatchString(s)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// intersectionSelector returns a selector that matches nodes that match
|
||||||
|
// both a and b.
|
||||||
|
func intersectionSelector(a, b Selector) Selector {
|
||||||
|
return func(n *html.Node) bool {
|
||||||
|
return a(n) && b(n)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// unionSelector returns a selector that matches elements that match
|
||||||
|
// either a or b.
|
||||||
|
func unionSelector(a, b Selector) Selector {
|
||||||
|
return func(n *html.Node) bool {
|
||||||
|
return a(n) || b(n)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// negatedSelector returns a selector that matches elements that do not match a.
|
||||||
|
func negatedSelector(a Selector) Selector {
|
||||||
|
return func(n *html.Node) bool {
|
||||||
|
if n.Type != html.ElementNode {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return !a(n)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// writeNodeText writes the text contained in n and its descendants to b.
|
||||||
|
func writeNodeText(n *html.Node, b *bytes.Buffer) {
|
||||||
|
switch n.Type {
|
||||||
|
case html.TextNode:
|
||||||
|
b.WriteString(n.Data)
|
||||||
|
case html.ElementNode:
|
||||||
|
for c := n.FirstChild; c != nil; c = c.NextSibling {
|
||||||
|
writeNodeText(c, b)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// nodeText returns the text contained in n and its descendants.
|
||||||
|
func nodeText(n *html.Node) string {
|
||||||
|
var b bytes.Buffer
|
||||||
|
writeNodeText(n, &b)
|
||||||
|
return b.String()
|
||||||
|
}
|
||||||
|
|
||||||
|
// nodeOwnText returns the contents of the text nodes that are direct
|
||||||
|
// children of n.
|
||||||
|
func nodeOwnText(n *html.Node) string {
|
||||||
|
var b bytes.Buffer
|
||||||
|
for c := n.FirstChild; c != nil; c = c.NextSibling {
|
||||||
|
if c.Type == html.TextNode {
|
||||||
|
b.WriteString(c.Data)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return b.String()
|
||||||
|
}
|
||||||
|
|
||||||
|
// textSubstrSelector returns a selector that matches nodes that
|
||||||
|
// contain the given text.
|
||||||
|
func textSubstrSelector(val string) Selector {
|
||||||
|
return func(n *html.Node) bool {
|
||||||
|
text := strings.ToLower(nodeText(n))
|
||||||
|
return strings.Contains(text, val)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ownTextSubstrSelector returns a selector that matches nodes that
|
||||||
|
// directly contain the given text
|
||||||
|
func ownTextSubstrSelector(val string) Selector {
|
||||||
|
return func(n *html.Node) bool {
|
||||||
|
text := strings.ToLower(nodeOwnText(n))
|
||||||
|
return strings.Contains(text, val)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// textRegexSelector returns a selector that matches nodes whose text matches
|
||||||
|
// the specified regular expression
|
||||||
|
func textRegexSelector(rx *regexp.Regexp) Selector {
|
||||||
|
return func(n *html.Node) bool {
|
||||||
|
return rx.MatchString(nodeText(n))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ownTextRegexSelector returns a selector that matches nodes whose text
|
||||||
|
// directly matches the specified regular expression
|
||||||
|
func ownTextRegexSelector(rx *regexp.Regexp) Selector {
|
||||||
|
return func(n *html.Node) bool {
|
||||||
|
return rx.MatchString(nodeOwnText(n))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// hasChildSelector returns a selector that matches elements
|
||||||
|
// with a child that matches a.
|
||||||
|
func hasChildSelector(a Selector) Selector {
|
||||||
|
return func(n *html.Node) bool {
|
||||||
|
if n.Type != html.ElementNode {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return hasChildMatch(n, a)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// hasDescendantSelector returns a selector that matches elements
|
||||||
|
// with any descendant that matches a.
|
||||||
|
func hasDescendantSelector(a Selector) Selector {
|
||||||
|
return func(n *html.Node) bool {
|
||||||
|
if n.Type != html.ElementNode {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return hasDescendantMatch(n, a)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// nthChildSelector returns a selector that implements :nth-child(an+b).
|
||||||
|
// If last is true, implements :nth-last-child instead.
|
||||||
|
// If ofType is true, implements :nth-of-type instead.
|
||||||
|
func nthChildSelector(a, b int, last, ofType bool) Selector {
|
||||||
|
return func(n *html.Node) bool {
|
||||||
|
if n.Type != html.ElementNode {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
parent := n.Parent
|
||||||
|
if parent == nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
i := -1
|
||||||
|
count := 0
|
||||||
|
for c := parent.FirstChild; c != nil; c = c.NextSibling {
|
||||||
|
if (c.Type != html.ElementNode) || (ofType && c.Data != n.Data) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
count++
|
||||||
|
if c == n {
|
||||||
|
i = count
|
||||||
|
if !last {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if i == -1 {
|
||||||
|
// This shouldn't happen, since n should always be one of its parent's children.
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
if last {
|
||||||
|
i = count - i + 1
|
||||||
|
}
|
||||||
|
|
||||||
|
i -= b
|
||||||
|
if a == 0 {
|
||||||
|
return i == 0
|
||||||
|
}
|
||||||
|
|
||||||
|
return i%a == 0 && i/a >= 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// onlyChildSelector returns a selector that implements :only-child.
|
||||||
|
// If ofType is true, it implements :only-of-type instead.
|
||||||
|
func onlyChildSelector(ofType bool) Selector {
|
||||||
|
return func(n *html.Node) bool {
|
||||||
|
if n.Type != html.ElementNode {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
parent := n.Parent
|
||||||
|
if parent == nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
count := 0
|
||||||
|
for c := parent.FirstChild; c != nil; c = c.NextSibling {
|
||||||
|
if (c.Type != html.ElementNode) || (ofType && c.Data != n.Data) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
count++
|
||||||
|
if count > 1 {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return count == 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// inputSelector is a Selector that matches input, select, textarea and button elements.
|
||||||
|
func inputSelector(n *html.Node) bool {
|
||||||
|
return n.Type == html.ElementNode && (n.Data == "input" || n.Data == "select" || n.Data == "textarea" || n.Data == "button")
|
||||||
|
}
|
||||||
|
|
||||||
|
// emptyElementSelector is a Selector that matches empty elements.
|
||||||
|
func emptyElementSelector(n *html.Node) bool {
|
||||||
|
if n.Type != html.ElementNode {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
for c := n.FirstChild; c != nil; c = c.NextSibling {
|
||||||
|
switch c.Type {
|
||||||
|
case html.ElementNode, html.TextNode:
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// descendantSelector returns a Selector that matches an element if
|
||||||
|
// it matches d and has an ancestor that matches a.
|
||||||
|
func descendantSelector(a, d Selector) Selector {
|
||||||
|
return func(n *html.Node) bool {
|
||||||
|
if !d(n) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
for p := n.Parent; p != nil; p = p.Parent {
|
||||||
|
if a(p) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// childSelector returns a Selector that matches an element if
|
||||||
|
// it matches d and its parent matches a.
|
||||||
|
func childSelector(a, d Selector) Selector {
|
||||||
|
return func(n *html.Node) bool {
|
||||||
|
return d(n) && n.Parent != nil && a(n.Parent)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// siblingSelector returns a Selector that matches an element
|
||||||
|
// if it matches s2 and in is preceded by an element that matches s1.
|
||||||
|
// If adjacent is true, the sibling must be immediately before the element.
|
||||||
|
func siblingSelector(s1, s2 Selector, adjacent bool) Selector {
|
||||||
|
return func(n *html.Node) bool {
|
||||||
|
if !s2(n) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
if adjacent {
|
||||||
|
for n = n.PrevSibling; n != nil; n = n.PrevSibling {
|
||||||
|
if n.Type == html.TextNode || n.Type == html.CommentNode {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
return s1(n)
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// Walk backwards looking for element that matches s1
|
||||||
|
for c := n.PrevSibling; c != nil; c = c.PrevSibling {
|
||||||
|
if s1(c) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
559
Godeps/_workspace/src/github.com/andybalholm/cascadia/selector_test.go
generated
vendored
Normal file
559
Godeps/_workspace/src/github.com/andybalholm/cascadia/selector_test.go
generated
vendored
Normal file
|
@ -0,0 +1,559 @@
|
||||||
|
package cascadia
|
||||||
|
|
||||||
|
import (
|
||||||
|
"strings"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"golang.org/x/net/html"
|
||||||
|
)
|
||||||
|
|
||||||
|
type selectorTest struct {
|
||||||
|
HTML, selector string
|
||||||
|
results []string
|
||||||
|
}
|
||||||
|
|
||||||
|
func nodeString(n *html.Node) string {
|
||||||
|
switch n.Type {
|
||||||
|
case html.TextNode:
|
||||||
|
return n.Data
|
||||||
|
case html.ElementNode:
|
||||||
|
return html.Token{
|
||||||
|
Type: html.StartTagToken,
|
||||||
|
Data: n.Data,
|
||||||
|
Attr: n.Attr,
|
||||||
|
}.String()
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
var selectorTests = []selectorTest{
|
||||||
|
{
|
||||||
|
`<body><address>This address...</address></body>`,
|
||||||
|
"address",
|
||||||
|
[]string{
|
||||||
|
"<address>",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
`<html><head></head><body></body></html>`,
|
||||||
|
"*",
|
||||||
|
[]string{
|
||||||
|
"",
|
||||||
|
"<html>",
|
||||||
|
"<head>",
|
||||||
|
"<body>",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
`<p id="foo"><p id="bar">`,
|
||||||
|
"#foo",
|
||||||
|
[]string{
|
||||||
|
`<p id="foo">`,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
`<ul><li id="t1"><p id="t1">`,
|
||||||
|
"li#t1",
|
||||||
|
[]string{
|
||||||
|
`<li id="t1">`,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
`<ol><li id="t4"><li id="t44">`,
|
||||||
|
"*#t4",
|
||||||
|
[]string{
|
||||||
|
`<li id="t4">`,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
`<ul><li class="t1"><li class="t2">`,
|
||||||
|
".t1",
|
||||||
|
[]string{
|
||||||
|
`<li class="t1">`,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
`<p class="t1 t2">`,
|
||||||
|
"p.t1",
|
||||||
|
[]string{
|
||||||
|
`<p class="t1 t2">`,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
`<div class="test">`,
|
||||||
|
"div.teST",
|
||||||
|
[]string{},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
`<p class="t1 t2">`,
|
||||||
|
".t1.fail",
|
||||||
|
[]string{},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
`<p class="t1 t2">`,
|
||||||
|
"p.t1.t2",
|
||||||
|
[]string{
|
||||||
|
`<p class="t1 t2">`,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
`<p><p title="title">`,
|
||||||
|
"p[title]",
|
||||||
|
[]string{
|
||||||
|
`<p title="title">`,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
`<address><address title="foo"><address title="bar">`,
|
||||||
|
`address[title="foo"]`,
|
||||||
|
[]string{
|
||||||
|
`<address title="foo">`,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
`<p title="tot foo bar">`,
|
||||||
|
`[ title ~= foo ]`,
|
||||||
|
[]string{
|
||||||
|
`<p title="tot foo bar">`,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
`<p title="hello world">`,
|
||||||
|
`[title~="hello world"]`,
|
||||||
|
[]string{},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
`<p lang="en"><p lang="en-gb"><p lang="enough"><p lang="fr-en">`,
|
||||||
|
`[lang|="en"]`,
|
||||||
|
[]string{
|
||||||
|
`<p lang="en">`,
|
||||||
|
`<p lang="en-gb">`,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
`<p title="foobar"><p title="barfoo">`,
|
||||||
|
`[title^="foo"]`,
|
||||||
|
[]string{
|
||||||
|
`<p title="foobar">`,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
`<p title="foobar"><p title="barfoo">`,
|
||||||
|
`[title$="bar"]`,
|
||||||
|
[]string{
|
||||||
|
`<p title="foobar">`,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
`<p title="foobarufoo">`,
|
||||||
|
`[title*="bar"]`,
|
||||||
|
[]string{
|
||||||
|
`<p title="foobarufoo">`,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
`<p class="t1 t2">`,
|
||||||
|
".t1:not(.t2)",
|
||||||
|
[]string{},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
`<div class="t3">`,
|
||||||
|
`div:not(.t1)`,
|
||||||
|
[]string{
|
||||||
|
`<div class="t3">`,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
`<ol><li id=1><li id=2><li id=3></ol>`,
|
||||||
|
`li:nth-child(odd)`,
|
||||||
|
[]string{
|
||||||
|
`<li id="1">`,
|
||||||
|
`<li id="3">`,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
`<ol><li id=1><li id=2><li id=3></ol>`,
|
||||||
|
`li:nth-child(even)`,
|
||||||
|
[]string{
|
||||||
|
`<li id="2">`,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
`<ol><li id=1><li id=2><li id=3></ol>`,
|
||||||
|
`li:nth-child(-n+2)`,
|
||||||
|
[]string{
|
||||||
|
`<li id="1">`,
|
||||||
|
`<li id="2">`,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
`<ol><li id=1><li id=2><li id=3></ol>`,
|
||||||
|
`li:nth-child(3n+1)`,
|
||||||
|
[]string{
|
||||||
|
`<li id="1">`,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
`<ol><li id=1><li id=2><li id=3><li id=4></ol>`,
|
||||||
|
`li:nth-last-child(odd)`,
|
||||||
|
[]string{
|
||||||
|
`<li id="2">`,
|
||||||
|
`<li id="4">`,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
`<ol><li id=1><li id=2><li id=3><li id=4></ol>`,
|
||||||
|
`li:nth-last-child(even)`,
|
||||||
|
[]string{
|
||||||
|
`<li id="1">`,
|
||||||
|
`<li id="3">`,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
`<ol><li id=1><li id=2><li id=3><li id=4></ol>`,
|
||||||
|
`li:nth-last-child(-n+2)`,
|
||||||
|
[]string{
|
||||||
|
`<li id="3">`,
|
||||||
|
`<li id="4">`,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
`<ol><li id=1><li id=2><li id=3><li id=4></ol>`,
|
||||||
|
`li:nth-last-child(3n+1)`,
|
||||||
|
[]string{
|
||||||
|
`<li id="1">`,
|
||||||
|
`<li id="4">`,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
`<p>some text <span id="1">and a span</span><span id="2"> and another</span></p>`,
|
||||||
|
`span:first-child`,
|
||||||
|
[]string{
|
||||||
|
`<span id="1">`,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
`<span>a span</span> and some text`,
|
||||||
|
`span:last-child`,
|
||||||
|
[]string{
|
||||||
|
`<span>`,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
`<address></address><p id=1><p id=2>`,
|
||||||
|
`p:nth-of-type(2)`,
|
||||||
|
[]string{
|
||||||
|
`<p id="2">`,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
`<address></address><p id=1><p id=2></p><a>`,
|
||||||
|
`p:nth-last-of-type(2)`,
|
||||||
|
[]string{
|
||||||
|
`<p id="1">`,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
`<address></address><p id=1><p id=2></p><a>`,
|
||||||
|
`p:last-of-type`,
|
||||||
|
[]string{
|
||||||
|
`<p id="2">`,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
`<address></address><p id=1><p id=2></p><a>`,
|
||||||
|
`p:first-of-type`,
|
||||||
|
[]string{
|
||||||
|
`<p id="1">`,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
`<div><p id="1"></p><a></a></div><div><p id="2"></p></div>`,
|
||||||
|
`p:only-child`,
|
||||||
|
[]string{
|
||||||
|
`<p id="2">`,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
`<div><p id="1"></p><a></a></div><div><p id="2"></p><p id="3"></p></div>`,
|
||||||
|
`p:only-of-type`,
|
||||||
|
[]string{
|
||||||
|
`<p id="1">`,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
`<p id="1"><!-- --><p id="2">Hello<p id="3"><span>`,
|
||||||
|
`:empty`,
|
||||||
|
[]string{
|
||||||
|
`<head>`,
|
||||||
|
`<p id="1">`,
|
||||||
|
`<span>`,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
`<div><p id="1"><table><tr><td><p id="2"></table></div><p id="3">`,
|
||||||
|
`div p`,
|
||||||
|
[]string{
|
||||||
|
`<p id="1">`,
|
||||||
|
`<p id="2">`,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
`<div><p id="1"><table><tr><td><p id="2"></table></div><p id="3">`,
|
||||||
|
`div table p`,
|
||||||
|
[]string{
|
||||||
|
`<p id="2">`,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
`<div><p id="1"><div><p id="2"></div><table><tr><td><p id="3"></table></div>`,
|
||||||
|
`div > p`,
|
||||||
|
[]string{
|
||||||
|
`<p id="1">`,
|
||||||
|
`<p id="2">`,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
`<p id="1"><p id="2"></p><address></address><p id="3">`,
|
||||||
|
`p ~ p`,
|
||||||
|
[]string{
|
||||||
|
`<p id="2">`,
|
||||||
|
`<p id="3">`,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
`<p id="1"></p>
|
||||||
|
<!--comment-->
|
||||||
|
<p id="2"></p><address></address><p id="3">`,
|
||||||
|
`p + p`,
|
||||||
|
[]string{
|
||||||
|
`<p id="2">`,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
`<ul><li></li><li></li></ul><p>`,
|
||||||
|
`li, p`,
|
||||||
|
[]string{
|
||||||
|
"<li>",
|
||||||
|
"<li>",
|
||||||
|
"<p>",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
`<p id="1"><p id="2"></p><address></address><p id="3">`,
|
||||||
|
`p +/*This is a comment*/ p`,
|
||||||
|
[]string{
|
||||||
|
`<p id="2">`,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
`<p>Text block that <span>wraps inner text</span> and continues</p>`,
|
||||||
|
`p:contains("that wraps")`,
|
||||||
|
[]string{
|
||||||
|
`<p>`,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
`<p>Text block that <span>wraps inner text</span> and continues</p>`,
|
||||||
|
`p:containsOwn("that wraps")`,
|
||||||
|
[]string{},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
`<p>Text block that <span>wraps inner text</span> and continues</p>`,
|
||||||
|
`:containsOwn("inner")`,
|
||||||
|
[]string{
|
||||||
|
`<span>`,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
`<p>Text block that <span>wraps inner text</span> and continues</p>`,
|
||||||
|
`p:containsOwn("block")`,
|
||||||
|
[]string{
|
||||||
|
`<p>`,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
`<div id="d1"><p id="p1"><span>text content</span></p></div><div id="d2"/>`,
|
||||||
|
`div:has(#p1)`,
|
||||||
|
[]string{
|
||||||
|
`<div id="d1">`,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
`<div id="d1"><p id="p1"><span>contents 1</span></p></div>
|
||||||
|
<div id="d2"><p>contents <em>2</em></p></div>`,
|
||||||
|
`div:has(:containsOwn("2"))`,
|
||||||
|
[]string{
|
||||||
|
`<div id="d2">`,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
`<body><div id="d1"><p id="p1"><span>contents 1</span></p></div>
|
||||||
|
<div id="d2"><p id="p2">contents <em>2</em></p></div></body>`,
|
||||||
|
`body :has(:containsOwn("2"))`,
|
||||||
|
[]string{
|
||||||
|
`<div id="d2">`,
|
||||||
|
`<p id="p2">`,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
`<body><div id="d1"><p id="p1"><span>contents 1</span></p></div>
|
||||||
|
<div id="d2"><p id="p2">contents <em>2</em></p></div></body>`,
|
||||||
|
`body :haschild(:containsOwn("2"))`,
|
||||||
|
[]string{
|
||||||
|
`<p id="p2">`,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
`<p id="p1">0123456789</p><p id="p2">abcdef</p><p id="p3">0123ABCD</p>`,
|
||||||
|
`p:matches([\d])`,
|
||||||
|
[]string{
|
||||||
|
`<p id="p1">`,
|
||||||
|
`<p id="p3">`,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
`<p id="p1">0123456789</p><p id="p2">abcdef</p><p id="p3">0123ABCD</p>`,
|
||||||
|
`p:matches([a-z])`,
|
||||||
|
[]string{
|
||||||
|
`<p id="p2">`,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
`<p id="p1">0123456789</p><p id="p2">abcdef</p><p id="p3">0123ABCD</p>`,
|
||||||
|
`p:matches([a-zA-Z])`,
|
||||||
|
[]string{
|
||||||
|
`<p id="p2">`,
|
||||||
|
`<p id="p3">`,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
`<p id="p1">0123456789</p><p id="p2">abcdef</p><p id="p3">0123ABCD</p>`,
|
||||||
|
`p:matches([^\d])`,
|
||||||
|
[]string{
|
||||||
|
`<p id="p2">`,
|
||||||
|
`<p id="p3">`,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
`<p id="p1">0123456789</p><p id="p2">abcdef</p><p id="p3">0123ABCD</p>`,
|
||||||
|
`p:matches(^(0|a))`,
|
||||||
|
[]string{
|
||||||
|
`<p id="p1">`,
|
||||||
|
`<p id="p2">`,
|
||||||
|
`<p id="p3">`,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
`<p id="p1">0123456789</p><p id="p2">abcdef</p><p id="p3">0123ABCD</p>`,
|
||||||
|
`p:matches(^\d+$)`,
|
||||||
|
[]string{
|
||||||
|
`<p id="p1">`,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
`<p id="p1">0123456789</p><p id="p2">abcdef</p><p id="p3">0123ABCD</p>`,
|
||||||
|
`p:not(:matches(^\d+$))`,
|
||||||
|
[]string{
|
||||||
|
`<p id="p2">`,
|
||||||
|
`<p id="p3">`,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
`<div><p id="p1">01234<em>567</em>89</p><div>`,
|
||||||
|
`div :matchesOwn(^\d+$)`,
|
||||||
|
[]string{
|
||||||
|
`<p id="p1">`,
|
||||||
|
`<em>`,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
`<ul>
|
||||||
|
<li><a id="a1" href="http://www.google.com/finance"/>
|
||||||
|
<li><a id="a2" href="http://finance.yahoo.com/"/>
|
||||||
|
<li><a id="a2" href="http://finance.untrusted.com/"/>
|
||||||
|
<li><a id="a3" href="https://www.google.com/news"/>
|
||||||
|
<li><a id="a4" href="http://news.yahoo.com"/>
|
||||||
|
</ul>`,
|
||||||
|
`[href#=(fina)]:not([href#=(\/\/[^\/]+untrusted)])`,
|
||||||
|
[]string{
|
||||||
|
`<a id="a1" href="http://www.google.com/finance">`,
|
||||||
|
`<a id="a2" href="http://finance.yahoo.com/">`,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
`<ul>
|
||||||
|
<li><a id="a1" href="http://www.google.com/finance"/>
|
||||||
|
<li><a id="a2" href="http://finance.yahoo.com/"/>
|
||||||
|
<li><a id="a3" href="https://www.google.com/news"/>
|
||||||
|
<li><a id="a4" href="http://news.yahoo.com"/>
|
||||||
|
</ul>`,
|
||||||
|
`[href#=(^https:\/\/[^\/]*\/?news)]`,
|
||||||
|
[]string{
|
||||||
|
`<a id="a3" href="https://www.google.com/news">`,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
`<form>
|
||||||
|
<label>Username <input type="text" name="username" /></label>
|
||||||
|
<label>Password <input type="password" name="password" /></label>
|
||||||
|
<label>Country
|
||||||
|
<select name="country">
|
||||||
|
<option value="ca">Canada</option>
|
||||||
|
<option value="us">United States</option>
|
||||||
|
</select>
|
||||||
|
</label>
|
||||||
|
<label>Bio <textarea name="bio"></textarea></label>
|
||||||
|
<button>Sign up</button>
|
||||||
|
</form>`,
|
||||||
|
`:input`,
|
||||||
|
[]string{
|
||||||
|
`<input type="text" name="username">`,
|
||||||
|
`<input type="password" name="password">`,
|
||||||
|
`<select name="country">`,
|
||||||
|
`<textarea name="bio">`,
|
||||||
|
`<button>`,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSelectors(t *testing.T) {
|
||||||
|
for _, test := range selectorTests {
|
||||||
|
s, err := Compile(test.selector)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("error compiling %q: %s", test.selector, err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
doc, err := html.Parse(strings.NewReader(test.HTML))
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("error parsing %q: %s", test.HTML, err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
matches := s.MatchAll(doc)
|
||||||
|
if len(matches) != len(test.results) {
|
||||||
|
t.Errorf("wanted %d elements, got %d instead", len(test.results), len(matches))
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
for i, m := range matches {
|
||||||
|
got := nodeString(m)
|
||||||
|
if got != test.results[i] {
|
||||||
|
t.Errorf("wanted %s, got %s instead", test.results[i], got)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
firstMatch := s.MatchFirst(doc)
|
||||||
|
if len(test.results) == 0 {
|
||||||
|
if firstMatch != nil {
|
||||||
|
t.Errorf("MatchFirst: want nil, got %s", nodeString(firstMatch))
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
got := nodeString(firstMatch)
|
||||||
|
if got != test.results[0] {
|
||||||
|
t.Errorf("MatchFirst: want %s, got %s", test.results[0], got)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
8
Godeps/_workspace/src/github.com/coopernurse/gorp/.gitignore
generated
vendored
Normal file
8
Godeps/_workspace/src/github.com/coopernurse/gorp/.gitignore
generated
vendored
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
_test
|
||||||
|
_testmain.go
|
||||||
|
_obj
|
||||||
|
*~
|
||||||
|
*.6
|
||||||
|
6.out
|
||||||
|
gorptest.bin
|
||||||
|
tmp
|
21
Godeps/_workspace/src/github.com/coopernurse/gorp/.travis.yml
generated
vendored
Normal file
21
Godeps/_workspace/src/github.com/coopernurse/gorp/.travis.yml
generated
vendored
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
language: go
|
||||||
|
go:
|
||||||
|
- 1.1
|
||||||
|
- tip
|
||||||
|
|
||||||
|
services:
|
||||||
|
- mysql
|
||||||
|
- postgres
|
||||||
|
- sqlite3
|
||||||
|
|
||||||
|
before_script:
|
||||||
|
- mysql -e "CREATE DATABASE gorptest;"
|
||||||
|
- mysql -u root -e "GRANT ALL ON gorptest.* TO gorptest@localhost IDENTIFIED BY 'gorptest'"
|
||||||
|
- psql -c "CREATE DATABASE gorptest;" -U postgres
|
||||||
|
- psql -c "CREATE USER "gorptest" WITH SUPERUSER PASSWORD 'gorptest';" -U postgres
|
||||||
|
- go get github.com/lib/pq
|
||||||
|
- go get github.com/mattn/go-sqlite3
|
||||||
|
- go get github.com/ziutek/mymysql/godrv
|
||||||
|
- go get github.com/go-sql-driver/mysql
|
||||||
|
|
||||||
|
script: ./test_all.sh
|
22
Godeps/_workspace/src/github.com/coopernurse/gorp/LICENSE
generated
vendored
Normal file
22
Godeps/_workspace/src/github.com/coopernurse/gorp/LICENSE
generated
vendored
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
(The MIT License)
|
||||||
|
|
||||||
|
Copyright (c) 2012 James Cooper <james@bitmechanic.com>
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining
|
||||||
|
a copy of this software and associated documentation files (the
|
||||||
|
'Software'), to deal in the Software without restriction, including
|
||||||
|
without limitation the rights to use, copy, modify, merge, publish,
|
||||||
|
distribute, sublicense, and/or sell copies of the Software, and to
|
||||||
|
permit persons to whom the Software is furnished to do so, subject to
|
||||||
|
the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be
|
||||||
|
included in all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||||
|
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||||
|
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||||
|
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||||
|
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
6
Godeps/_workspace/src/github.com/coopernurse/gorp/Makefile
generated
vendored
Normal file
6
Godeps/_workspace/src/github.com/coopernurse/gorp/Makefile
generated
vendored
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
include $(GOROOT)/src/Make.inc
|
||||||
|
|
||||||
|
TARG = github.com/coopernurse/gorp
|
||||||
|
GOFILES = gorp.go dialect.go
|
||||||
|
|
||||||
|
include $(GOROOT)/src/Make.pkg
|
655
Godeps/_workspace/src/github.com/coopernurse/gorp/README.md
generated
vendored
Normal file
655
Godeps/_workspace/src/github.com/coopernurse/gorp/README.md
generated
vendored
Normal file
|
@ -0,0 +1,655 @@
|
||||||
|
# Go Relational Persistence #
|
||||||
|
|
||||||
|
[![build status](https://secure.travis-ci.org/coopernurse/gorp.png)](http://travis-ci.org/coopernurse/gorp)
|
||||||
|
|
||||||
|
I hesitate to call gorp an ORM. Go doesn't really have objects, at least
|
||||||
|
not in the classic Smalltalk/Java sense. There goes the "O". gorp doesn't
|
||||||
|
know anything about the relationships between your structs (at least not
|
||||||
|
yet). So the "R" is questionable too (but I use it in the name because,
|
||||||
|
well, it seemed more clever).
|
||||||
|
|
||||||
|
The "M" is alive and well. Given some Go structs and a database, gorp
|
||||||
|
should remove a fair amount of boilerplate busy-work from your code.
|
||||||
|
|
||||||
|
I hope that gorp saves you time, minimizes the drudgery of getting data
|
||||||
|
in and out of your database, and helps your code focus on algorithms,
|
||||||
|
not infrastructure.
|
||||||
|
|
||||||
|
* Bind struct fields to table columns via API or tag
|
||||||
|
* Support for embedded structs
|
||||||
|
* Support for transactions
|
||||||
|
* Forward engineer db schema from structs (great for unit tests)
|
||||||
|
* Pre/post insert/update/delete hooks
|
||||||
|
* Automatically generate insert/update/delete statements for a struct
|
||||||
|
* Automatic binding of auto increment PKs back to struct after insert
|
||||||
|
* Delete by primary key(s)
|
||||||
|
* Select by primary key(s)
|
||||||
|
* Optional trace sql logging
|
||||||
|
* Bind arbitrary SQL queries to a struct
|
||||||
|
* Bind slice to SELECT query results without type assertions
|
||||||
|
* Use positional or named bind parameters in custom SELECT queries
|
||||||
|
* Optional optimistic locking using a version column (for update/deletes)
|
||||||
|
|
||||||
|
## Installation ##
|
||||||
|
|
||||||
|
# install the library:
|
||||||
|
go get github.com/coopernurse/gorp
|
||||||
|
|
||||||
|
// use in your .go code:
|
||||||
|
import (
|
||||||
|
"github.com/coopernurse/gorp"
|
||||||
|
)
|
||||||
|
|
||||||
|
## API Documentation ##
|
||||||
|
|
||||||
|
Full godoc output from the latest code in master is available here:
|
||||||
|
|
||||||
|
http://godoc.org/github.com/coopernurse/gorp
|
||||||
|
|
||||||
|
## Quickstart
|
||||||
|
|
||||||
|
```go
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"database/sql"
|
||||||
|
"github.com/coopernurse/gorp"
|
||||||
|
_ "github.com/mattn/go-sqlite3"
|
||||||
|
"log"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
// initialize the DbMap
|
||||||
|
dbmap := initDb()
|
||||||
|
defer dbmap.Db.Close()
|
||||||
|
|
||||||
|
// delete any existing rows
|
||||||
|
err := dbmap.TruncateTables()
|
||||||
|
checkErr(err, "TruncateTables failed")
|
||||||
|
|
||||||
|
// create two posts
|
||||||
|
p1 := newPost("Go 1.1 released!", "Lorem ipsum lorem ipsum")
|
||||||
|
p2 := newPost("Go 1.2 released!", "Lorem ipsum lorem ipsum")
|
||||||
|
|
||||||
|
// insert rows - auto increment PKs will be set properly after the insert
|
||||||
|
err = dbmap.Insert(&p1, &p2)
|
||||||
|
checkErr(err, "Insert failed")
|
||||||
|
|
||||||
|
// use convenience SelectInt
|
||||||
|
count, err := dbmap.SelectInt("select count(*) from posts")
|
||||||
|
checkErr(err, "select count(*) failed")
|
||||||
|
log.Println("Rows after inserting:", count)
|
||||||
|
|
||||||
|
// update a row
|
||||||
|
p2.Title = "Go 1.2 is better than ever"
|
||||||
|
count, err = dbmap.Update(&p2)
|
||||||
|
checkErr(err, "Update failed")
|
||||||
|
log.Println("Rows updated:", count)
|
||||||
|
|
||||||
|
// fetch one row - note use of "post_id" instead of "Id" since column is aliased
|
||||||
|
//
|
||||||
|
// Postgres users should use $1 instead of ? placeholders
|
||||||
|
// See 'Known Issues' below
|
||||||
|
//
|
||||||
|
err = dbmap.SelectOne(&p2, "select * from posts where post_id=?", p2.Id)
|
||||||
|
checkErr(err, "SelectOne failed")
|
||||||
|
log.Println("p2 row:", p2)
|
||||||
|
|
||||||
|
// fetch all rows
|
||||||
|
var posts []Post
|
||||||
|
_, err = dbmap.Select(&posts, "select * from posts order by post_id")
|
||||||
|
checkErr(err, "Select failed")
|
||||||
|
log.Println("All rows:")
|
||||||
|
for x, p := range posts {
|
||||||
|
log.Printf(" %d: %v\n", x, p)
|
||||||
|
}
|
||||||
|
|
||||||
|
// delete row by PK
|
||||||
|
count, err = dbmap.Delete(&p1)
|
||||||
|
checkErr(err, "Delete failed")
|
||||||
|
log.Println("Rows deleted:", count)
|
||||||
|
|
||||||
|
// delete row manually via Exec
|
||||||
|
_, err = dbmap.Exec("delete from posts where post_id=?", p2.Id)
|
||||||
|
checkErr(err, "Exec failed")
|
||||||
|
|
||||||
|
// confirm count is zero
|
||||||
|
count, err = dbmap.SelectInt("select count(*) from posts")
|
||||||
|
checkErr(err, "select count(*) failed")
|
||||||
|
log.Println("Row count - should be zero:", count)
|
||||||
|
|
||||||
|
log.Println("Done!")
|
||||||
|
}
|
||||||
|
|
||||||
|
type Post struct {
|
||||||
|
// db tag lets you specify the column name if it differs from the struct field
|
||||||
|
Id int64 `db:"post_id"`
|
||||||
|
Created int64
|
||||||
|
Title string
|
||||||
|
Body string
|
||||||
|
}
|
||||||
|
|
||||||
|
func newPost(title, body string) Post {
|
||||||
|
return Post{
|
||||||
|
Created: time.Now().UnixNano(),
|
||||||
|
Title: title,
|
||||||
|
Body: body,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func initDb() *gorp.DbMap {
|
||||||
|
// connect to db using standard Go database/sql API
|
||||||
|
// use whatever database/sql driver you wish
|
||||||
|
db, err := sql.Open("sqlite3", "/tmp/post_db.bin")
|
||||||
|
checkErr(err, "sql.Open failed")
|
||||||
|
|
||||||
|
// construct a gorp DbMap
|
||||||
|
dbmap := &gorp.DbMap{Db: db, Dialect: gorp.SqliteDialect{}}
|
||||||
|
|
||||||
|
// add a table, setting the table name to 'posts' and
|
||||||
|
// specifying that the Id property is an auto incrementing PK
|
||||||
|
dbmap.AddTableWithName(Post{}, "posts").SetKeys(true, "Id")
|
||||||
|
|
||||||
|
// create the table. in a production system you'd generally
|
||||||
|
// use a migration tool, or create the tables via scripts
|
||||||
|
err = dbmap.CreateTablesIfNotExists()
|
||||||
|
checkErr(err, "Create tables failed")
|
||||||
|
|
||||||
|
return dbmap
|
||||||
|
}
|
||||||
|
|
||||||
|
func checkErr(err error, msg string) {
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalln(msg, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Examples ##
|
||||||
|
|
||||||
|
### Mapping structs to tables ###
|
||||||
|
|
||||||
|
First define some types:
|
||||||
|
|
||||||
|
```go
|
||||||
|
type Invoice struct {
|
||||||
|
Id int64
|
||||||
|
Created int64
|
||||||
|
Updated int64
|
||||||
|
Memo string
|
||||||
|
PersonId int64
|
||||||
|
}
|
||||||
|
|
||||||
|
type Person struct {
|
||||||
|
Id int64
|
||||||
|
Created int64
|
||||||
|
Updated int64
|
||||||
|
FName string
|
||||||
|
LName string
|
||||||
|
}
|
||||||
|
|
||||||
|
// Example of using tags to alias fields to column names
|
||||||
|
// The 'db' value is the column name
|
||||||
|
//
|
||||||
|
// A hyphen will cause gorp to skip this field, similar to the
|
||||||
|
// Go json package.
|
||||||
|
//
|
||||||
|
// This is equivalent to using the ColMap methods:
|
||||||
|
//
|
||||||
|
// table := dbmap.AddTableWithName(Product{}, "product")
|
||||||
|
// table.ColMap("Id").Rename("product_id")
|
||||||
|
// table.ColMap("Price").Rename("unit_price")
|
||||||
|
// table.ColMap("IgnoreMe").SetTransient(true)
|
||||||
|
//
|
||||||
|
type Product struct {
|
||||||
|
Id int64 `db:"product_id"`
|
||||||
|
Price int64 `db:"unit_price"`
|
||||||
|
IgnoreMe string `db:"-"`
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Then create a mapper, typically you'd do this one time at app startup:
|
||||||
|
|
||||||
|
```go
|
||||||
|
// connect to db using standard Go database/sql API
|
||||||
|
// use whatever database/sql driver you wish
|
||||||
|
db, err := sql.Open("mymysql", "tcp:localhost:3306*mydb/myuser/mypassword")
|
||||||
|
|
||||||
|
// construct a gorp DbMap
|
||||||
|
dbmap := &gorp.DbMap{Db: db, Dialect: gorp.MySQLDialect{"InnoDB", "UTF8"}}
|
||||||
|
|
||||||
|
// register the structs you wish to use with gorp
|
||||||
|
// you can also use the shorter dbmap.AddTable() if you
|
||||||
|
// don't want to override the table name
|
||||||
|
//
|
||||||
|
// SetKeys(true) means we have a auto increment primary key, which
|
||||||
|
// will get automatically bound to your struct post-insert
|
||||||
|
//
|
||||||
|
t1 := dbmap.AddTableWithName(Invoice{}, "invoice_test").SetKeys(true, "Id")
|
||||||
|
t2 := dbmap.AddTableWithName(Person{}, "person_test").SetKeys(true, "Id")
|
||||||
|
t3 := dbmap.AddTableWithName(Product{}, "product_test").SetKeys(true, "Id")
|
||||||
|
```
|
||||||
|
|
||||||
|
### Struct Embedding ###
|
||||||
|
|
||||||
|
gorp supports embedding structs. For example:
|
||||||
|
|
||||||
|
```go
|
||||||
|
type Names struct {
|
||||||
|
FirstName string
|
||||||
|
LastName string
|
||||||
|
}
|
||||||
|
|
||||||
|
type WithEmbeddedStruct struct {
|
||||||
|
Id int64
|
||||||
|
Names
|
||||||
|
}
|
||||||
|
|
||||||
|
es := &WithEmbeddedStruct{-1, Names{FirstName: "Alice", LastName: "Smith"}}
|
||||||
|
err := dbmap.Insert(es)
|
||||||
|
```
|
||||||
|
|
||||||
|
See the `TestWithEmbeddedStruct` function in `gorp_test.go` for a full example.
|
||||||
|
|
||||||
|
### Create/Drop Tables ###
|
||||||
|
|
||||||
|
Automatically create / drop registered tables. This is useful for unit tests
|
||||||
|
but is entirely optional. You can of course use gorp with tables created manually,
|
||||||
|
or with a separate migration tool (like goose: https://bitbucket.org/liamstask/goose).
|
||||||
|
|
||||||
|
```go
|
||||||
|
// create all registered tables
|
||||||
|
dbmap.CreateTables()
|
||||||
|
|
||||||
|
// same as above, but uses "if not exists" clause to skip tables that are
|
||||||
|
// already defined
|
||||||
|
dbmap.CreateTablesIfNotExists()
|
||||||
|
|
||||||
|
// drop
|
||||||
|
dbmap.DropTables()
|
||||||
|
```
|
||||||
|
|
||||||
|
### SQL Logging ###
|
||||||
|
|
||||||
|
Optionally you can pass in a logger to trace all SQL statements.
|
||||||
|
I recommend enabling this initially while you're getting the feel for what
|
||||||
|
gorp is doing on your behalf.
|
||||||
|
|
||||||
|
Gorp defines a `GorpLogger` interface that Go's built in `log.Logger` satisfies.
|
||||||
|
However, you can write your own `GorpLogger` implementation, or use a package such
|
||||||
|
as `glog` if you want more control over how statements are logged.
|
||||||
|
|
||||||
|
```go
|
||||||
|
// Will log all SQL statements + args as they are run
|
||||||
|
// The first arg is a string prefix to prepend to all log messages
|
||||||
|
dbmap.TraceOn("[gorp]", log.New(os.Stdout, "myapp:", log.Lmicroseconds))
|
||||||
|
|
||||||
|
// Turn off tracing
|
||||||
|
dbmap.TraceOff()
|
||||||
|
```
|
||||||
|
|
||||||
|
### Insert ###
|
||||||
|
|
||||||
|
```go
|
||||||
|
// Must declare as pointers so optional callback hooks
|
||||||
|
// can operate on your data, not copies
|
||||||
|
inv1 := &Invoice{0, 100, 200, "first order", 0}
|
||||||
|
inv2 := &Invoice{0, 100, 200, "second order", 0}
|
||||||
|
|
||||||
|
// Insert your rows
|
||||||
|
err := dbmap.Insert(inv1, inv2)
|
||||||
|
|
||||||
|
// Because we called SetKeys(true) on Invoice, the Id field
|
||||||
|
// will be populated after the Insert() automatically
|
||||||
|
fmt.Printf("inv1.Id=%d inv2.Id=%d\n", inv1.Id, inv2.Id)
|
||||||
|
```
|
||||||
|
|
||||||
|
### Update ###
|
||||||
|
|
||||||
|
Continuing the above example, use the `Update` method to modify an Invoice:
|
||||||
|
|
||||||
|
```go
|
||||||
|
// count is the # of rows updated, which should be 1 in this example
|
||||||
|
count, err := dbmap.Update(inv1)
|
||||||
|
```
|
||||||
|
|
||||||
|
### Delete ###
|
||||||
|
|
||||||
|
If you have primary key(s) defined for a struct, you can use the `Delete`
|
||||||
|
method to remove rows:
|
||||||
|
|
||||||
|
```go
|
||||||
|
count, err := dbmap.Delete(inv1)
|
||||||
|
```
|
||||||
|
|
||||||
|
### Select by Key ###
|
||||||
|
|
||||||
|
Use the `Get` method to fetch a single row by primary key. It returns
|
||||||
|
nil if no row is found.
|
||||||
|
|
||||||
|
```go
|
||||||
|
// fetch Invoice with Id=99
|
||||||
|
obj, err := dbmap.Get(Invoice{}, 99)
|
||||||
|
inv := obj.(*Invoice)
|
||||||
|
```
|
||||||
|
|
||||||
|
### Ad Hoc SQL ###
|
||||||
|
|
||||||
|
#### SELECT ####
|
||||||
|
|
||||||
|
`Select()` and `SelectOne()` provide a simple way to bind arbitrary queries to a slice
|
||||||
|
or a single struct.
|
||||||
|
|
||||||
|
```go
|
||||||
|
// Select a slice - first return value is not needed when a slice pointer is passed to Select()
|
||||||
|
var posts []Post
|
||||||
|
_, err := dbmap.Select(&posts, "select * from post order by id")
|
||||||
|
|
||||||
|
// You can also use primitive types
|
||||||
|
var ids []string
|
||||||
|
_, err := dbmap.Select(&ids, "select id from post")
|
||||||
|
|
||||||
|
// Select a single row.
|
||||||
|
// Returns an error if no row found, or if more than one row is found
|
||||||
|
var post Post
|
||||||
|
err := dbmap.SelectOne(&post, "select * from post where id=?", id)
|
||||||
|
```
|
||||||
|
|
||||||
|
Want to do joins? Just write the SQL and the struct. gorp will bind them:
|
||||||
|
|
||||||
|
```go
|
||||||
|
// Define a type for your join
|
||||||
|
// It *must* contain all the columns in your SELECT statement
|
||||||
|
//
|
||||||
|
// The names here should match the aliased column names you specify
|
||||||
|
// in your SQL - no additional binding work required. simple.
|
||||||
|
//
|
||||||
|
type InvoicePersonView struct {
|
||||||
|
InvoiceId int64
|
||||||
|
PersonId int64
|
||||||
|
Memo string
|
||||||
|
FName string
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create some rows
|
||||||
|
p1 := &Person{0, 0, 0, "bob", "smith"}
|
||||||
|
dbmap.Insert(p1)
|
||||||
|
|
||||||
|
// notice how we can wire up p1.Id to the invoice easily
|
||||||
|
inv1 := &Invoice{0, 0, 0, "xmas order", p1.Id}
|
||||||
|
dbmap.Insert(inv1)
|
||||||
|
|
||||||
|
// Run your query
|
||||||
|
query := "select i.Id InvoiceId, p.Id PersonId, i.Memo, p.FName " +
|
||||||
|
"from invoice_test i, person_test p " +
|
||||||
|
"where i.PersonId = p.Id"
|
||||||
|
|
||||||
|
// pass a slice to Select()
|
||||||
|
var list []InvoicePersonView
|
||||||
|
_, err := dbmap.Select(&list, query)
|
||||||
|
|
||||||
|
// this should test true
|
||||||
|
expected := InvoicePersonView{inv1.Id, p1.Id, inv1.Memo, p1.FName}
|
||||||
|
if reflect.DeepEqual(list[0], expected) {
|
||||||
|
fmt.Println("Woot! My join worked!")
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### SELECT string or int64 ####
|
||||||
|
|
||||||
|
gorp provides a few convenience methods for selecting a single string or int64.
|
||||||
|
|
||||||
|
```go
|
||||||
|
// select single int64 from db (use $1 instead of ? for postgresql)
|
||||||
|
i64, err := dbmap.SelectInt("select count(*) from foo where blah=?", blahVal)
|
||||||
|
|
||||||
|
// select single string from db:
|
||||||
|
s, err := dbmap.SelectStr("select name from foo where blah=?", blahVal)
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Named bind parameters ####
|
||||||
|
|
||||||
|
You may use a map or struct to bind parameters by name. This is currently
|
||||||
|
only supported in SELECT queries.
|
||||||
|
|
||||||
|
```go
|
||||||
|
_, err := dbm.Select(&dest, "select * from Foo where name = :name and age = :age", map[string]interface{}{
|
||||||
|
"name": "Rob",
|
||||||
|
"age": 31,
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
#### UPDATE / DELETE ####
|
||||||
|
|
||||||
|
You can execute raw SQL if you wish. Particularly good for batch operations.
|
||||||
|
|
||||||
|
```go
|
||||||
|
res, err := dbmap.Exec("delete from invoice_test where PersonId=?", 10)
|
||||||
|
```
|
||||||
|
|
||||||
|
### Transactions ###
|
||||||
|
|
||||||
|
You can batch operations into a transaction:
|
||||||
|
|
||||||
|
```go
|
||||||
|
func InsertInv(dbmap *DbMap, inv *Invoice, per *Person) error {
|
||||||
|
// Start a new transaction
|
||||||
|
trans, err := dbmap.Begin()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
trans.Insert(per)
|
||||||
|
inv.PersonId = per.Id
|
||||||
|
trans.Insert(inv)
|
||||||
|
|
||||||
|
// if the commit is successful, a nil error is returned
|
||||||
|
return trans.Commit()
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Hooks ###
|
||||||
|
|
||||||
|
Use hooks to update data before/after saving to the db. Good for timestamps:
|
||||||
|
|
||||||
|
```go
|
||||||
|
// implement the PreInsert and PreUpdate hooks
|
||||||
|
func (i *Invoice) PreInsert(s gorp.SqlExecutor) error {
|
||||||
|
i.Created = time.Now().UnixNano()
|
||||||
|
i.Updated = i.Created
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (i *Invoice) PreUpdate(s gorp.SqlExecutor) error {
|
||||||
|
i.Updated = time.Now().UnixNano()
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// You can use the SqlExecutor to cascade additional SQL
|
||||||
|
// Take care to avoid cycles. gorp won't prevent them.
|
||||||
|
//
|
||||||
|
// Here's an example of a cascading delete
|
||||||
|
//
|
||||||
|
func (p *Person) PreDelete(s gorp.SqlExecutor) error {
|
||||||
|
query := "delete from invoice_test where PersonId=?"
|
||||||
|
err := s.Exec(query, p.Id); if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Full list of hooks that you can implement:
|
||||||
|
|
||||||
|
PostGet
|
||||||
|
PreInsert
|
||||||
|
PostInsert
|
||||||
|
PreUpdate
|
||||||
|
PostUpdate
|
||||||
|
PreDelete
|
||||||
|
PostDelete
|
||||||
|
|
||||||
|
All have the same signature. for example:
|
||||||
|
|
||||||
|
func (p *MyStruct) PostUpdate(s gorp.SqlExecutor) error
|
||||||
|
|
||||||
|
### Optimistic Locking ###
|
||||||
|
|
||||||
|
gorp provides a simple optimistic locking feature, similar to Java's JPA, that
|
||||||
|
will raise an error if you try to update/delete a row whose `version` column
|
||||||
|
has a value different than the one in memory. This provides a safe way to do
|
||||||
|
"select then update" style operations without explicit read and write locks.
|
||||||
|
|
||||||
|
```go
|
||||||
|
// Version is an auto-incremented number, managed by gorp
|
||||||
|
// If this property is present on your struct, update
|
||||||
|
// operations will be constrained
|
||||||
|
//
|
||||||
|
// For example, say we defined Person as:
|
||||||
|
|
||||||
|
type Person struct {
|
||||||
|
Id int64
|
||||||
|
Created int64
|
||||||
|
Updated int64
|
||||||
|
FName string
|
||||||
|
LName string
|
||||||
|
|
||||||
|
// automatically used as the Version col
|
||||||
|
// use table.SetVersionCol("columnName") to map a different
|
||||||
|
// struct field as the version field
|
||||||
|
Version int64
|
||||||
|
}
|
||||||
|
|
||||||
|
p1 := &Person{0, 0, 0, "Bob", "Smith", 0}
|
||||||
|
dbmap.Insert(p1) // Version is now 1
|
||||||
|
|
||||||
|
obj, err := dbmap.Get(Person{}, p1.Id)
|
||||||
|
p2 := obj.(*Person)
|
||||||
|
p2.LName = "Edwards"
|
||||||
|
dbmap.Update(p2) // Version is now 2
|
||||||
|
|
||||||
|
p1.LName = "Howard"
|
||||||
|
|
||||||
|
// Raises error because p1.Version == 1, which is out of date
|
||||||
|
count, err := dbmap.Update(p1)
|
||||||
|
_, ok := err.(gorp.OptimisticLockError)
|
||||||
|
if ok {
|
||||||
|
// should reach this statement
|
||||||
|
|
||||||
|
// in a real app you might reload the row and retry, or
|
||||||
|
// you might propegate this to the user, depending on the desired
|
||||||
|
// semantics
|
||||||
|
fmt.Printf("Tried to update row with stale data: %v\n", err)
|
||||||
|
} else {
|
||||||
|
// some other db error occurred - log or return up the stack
|
||||||
|
fmt.Printf("Unknown db err: %v\n", err)
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Database Drivers ##
|
||||||
|
|
||||||
|
gorp uses the Go 1 `database/sql` package. A full list of compliant drivers is available here:
|
||||||
|
|
||||||
|
http://code.google.com/p/go-wiki/wiki/SQLDrivers
|
||||||
|
|
||||||
|
Sadly, SQL databases differ on various issues. gorp provides a Dialect interface that should be
|
||||||
|
implemented per database vendor. Dialects are provided for:
|
||||||
|
|
||||||
|
* MySQL
|
||||||
|
* PostgreSQL
|
||||||
|
* sqlite3
|
||||||
|
|
||||||
|
Each of these three databases pass the test suite. See `gorp_test.go` for example
|
||||||
|
DSNs for these three databases.
|
||||||
|
|
||||||
|
Support is also provided for:
|
||||||
|
|
||||||
|
* Oracle (contributed by @klaidliadon)
|
||||||
|
* SQL Server (contributed by @qrawl) - use driver: github.com/denisenkom/go-mssqldb
|
||||||
|
|
||||||
|
Note that these databases are not covered by CI and I (@coopernurse) have no good way to
|
||||||
|
test them locally. So please try them and send patches as needed, but expect a bit more
|
||||||
|
unpredicability.
|
||||||
|
|
||||||
|
## Known Issues ##
|
||||||
|
|
||||||
|
### SQL placeholder portability ###
|
||||||
|
|
||||||
|
Different databases use different strings to indicate variable placeholders in
|
||||||
|
prepared SQL statements. Unlike some database abstraction layers (such as JDBC),
|
||||||
|
Go's `database/sql` does not standardize this.
|
||||||
|
|
||||||
|
SQL generated by gorp in the `Insert`, `Update`, `Delete`, and `Get` methods delegates
|
||||||
|
to a Dialect implementation for each database, and will generate portable SQL.
|
||||||
|
|
||||||
|
Raw SQL strings passed to `Exec`, `Select`, `SelectOne`, `SelectInt`, etc will not be
|
||||||
|
parsed. Consequently you may have portability issues if you write a query like this:
|
||||||
|
|
||||||
|
```go
|
||||||
|
// works on MySQL and Sqlite3, but not with Postgresql
|
||||||
|
err := dbmap.SelectOne(&val, "select * from foo where id = ?", 30)
|
||||||
|
```
|
||||||
|
|
||||||
|
In `Select` and `SelectOne` you can use named parameters to work around this.
|
||||||
|
The following is portable:
|
||||||
|
|
||||||
|
```go
|
||||||
|
err := dbmap.SelectOne(&val, "select * from foo where id = :id",
|
||||||
|
map[string]interface{} { "id": 30})
|
||||||
|
```
|
||||||
|
|
||||||
|
### time.Time and time zones ###
|
||||||
|
|
||||||
|
gorp will pass `time.Time` fields through to the `database/sql` driver, but note that
|
||||||
|
the behavior of this type varies across database drivers.
|
||||||
|
|
||||||
|
MySQL users should be especially cautious. See: https://github.com/ziutek/mymysql/pull/77
|
||||||
|
|
||||||
|
To avoid any potential issues with timezone/DST, consider using an integer field for time
|
||||||
|
data and storing UNIX time.
|
||||||
|
|
||||||
|
## Running the tests ##
|
||||||
|
|
||||||
|
The included tests may be run against MySQL, Postgresql, or sqlite3.
|
||||||
|
You must set two environment variables so the test code knows which driver to
|
||||||
|
use, and how to connect to your database.
|
||||||
|
|
||||||
|
```sh
|
||||||
|
# MySQL example:
|
||||||
|
export GORP_TEST_DSN=gomysql_test/gomysql_test/abc123
|
||||||
|
export GORP_TEST_DIALECT=mysql
|
||||||
|
|
||||||
|
# run the tests
|
||||||
|
go test
|
||||||
|
|
||||||
|
# run the tests and benchmarks
|
||||||
|
go test -bench="Bench" -benchtime 10
|
||||||
|
```
|
||||||
|
|
||||||
|
Valid `GORP_TEST_DIALECT` values are: "mysql", "postgres", "sqlite3"
|
||||||
|
See the `test_all.sh` script for examples of all 3 databases. This is the script I run
|
||||||
|
locally to test the library.
|
||||||
|
|
||||||
|
## Performance ##
|
||||||
|
|
||||||
|
gorp uses reflection to construct SQL queries and bind parameters. See the BenchmarkNativeCrud vs BenchmarkGorpCrud in gorp_test.go for a simple perf test. On my MacBook Pro gorp is about 2-3% slower than hand written SQL.
|
||||||
|
|
||||||
|
## Pull requests / Contributions
|
||||||
|
|
||||||
|
Contributions are very welcome. Please follow these guidelines:
|
||||||
|
|
||||||
|
* Fork the `develop` branch and issue pull requests targeting the `develop` branch
|
||||||
|
* If you don't do this, I'll likely cherry pick your commit into develop
|
||||||
|
* If you are adding an enhancement, please open an issue first with your proposed change.
|
||||||
|
* Changes that break backwards compatibility in the public API are only accepted after we
|
||||||
|
discuss on a GitHub issue for a while.
|
||||||
|
|
||||||
|
Thanks!
|
||||||
|
|
||||||
|
## Contributors
|
||||||
|
|
||||||
|
* matthias-margush - column aliasing via tags
|
||||||
|
* Rob Figueiredo - @robfig
|
||||||
|
* Quinn Slack - @sqs
|
692
Godeps/_workspace/src/github.com/coopernurse/gorp/dialect.go
generated
vendored
Normal file
692
Godeps/_workspace/src/github.com/coopernurse/gorp/dialect.go
generated
vendored
Normal file
|
@ -0,0 +1,692 @@
|
||||||
|
package gorp
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"reflect"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
// The Dialect interface encapsulates behaviors that differ across
|
||||||
|
// SQL databases. At present the Dialect is only used by CreateTables()
|
||||||
|
// but this could change in the future
|
||||||
|
type Dialect interface {
|
||||||
|
|
||||||
|
// adds a suffix to any query, usually ";"
|
||||||
|
QuerySuffix() string
|
||||||
|
|
||||||
|
// ToSqlType returns the SQL column type to use when creating a
|
||||||
|
// table of the given Go Type. maxsize can be used to switch based on
|
||||||
|
// size. For example, in MySQL []byte could map to BLOB, MEDIUMBLOB,
|
||||||
|
// or LONGBLOB depending on the maxsize
|
||||||
|
ToSqlType(val reflect.Type, maxsize int, isAutoIncr bool) string
|
||||||
|
|
||||||
|
// string to append to primary key column definitions
|
||||||
|
AutoIncrStr() string
|
||||||
|
|
||||||
|
// string to bind autoincrement columns to. Empty string will
|
||||||
|
// remove reference to those columns in the INSERT statement.
|
||||||
|
AutoIncrBindValue() string
|
||||||
|
|
||||||
|
AutoIncrInsertSuffix(col *ColumnMap) string
|
||||||
|
|
||||||
|
// string to append to "create table" statement for vendor specific
|
||||||
|
// table attributes
|
||||||
|
CreateTableSuffix() string
|
||||||
|
|
||||||
|
// string to truncate tables
|
||||||
|
TruncateClause() string
|
||||||
|
|
||||||
|
// bind variable string to use when forming SQL statements
|
||||||
|
// in many dbs it is "?", but Postgres appears to use $1
|
||||||
|
//
|
||||||
|
// i is a zero based index of the bind variable in this statement
|
||||||
|
//
|
||||||
|
BindVar(i int) string
|
||||||
|
|
||||||
|
// Handles quoting of a field name to ensure that it doesn't raise any
|
||||||
|
// SQL parsing exceptions by using a reserved word as a field name.
|
||||||
|
QuoteField(field string) string
|
||||||
|
|
||||||
|
// Handles building up of a schema.database string that is compatible with
|
||||||
|
// the given dialect
|
||||||
|
//
|
||||||
|
// schema - The schema that <table> lives in
|
||||||
|
// table - The table name
|
||||||
|
QuotedTableForQuery(schema string, table string) string
|
||||||
|
|
||||||
|
// Existance clause for table creation / deletion
|
||||||
|
IfSchemaNotExists(command, schema string) string
|
||||||
|
IfTableExists(command, schema, table string) string
|
||||||
|
IfTableNotExists(command, schema, table string) string
|
||||||
|
}
|
||||||
|
|
||||||
|
// IntegerAutoIncrInserter is implemented by dialects that can perform
|
||||||
|
// inserts with automatically incremented integer primary keys. If
|
||||||
|
// the dialect can handle automatic assignment of more than just
|
||||||
|
// integers, see TargetedAutoIncrInserter.
|
||||||
|
type IntegerAutoIncrInserter interface {
|
||||||
|
InsertAutoIncr(exec SqlExecutor, insertSql string, params ...interface{}) (int64, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
// TargetedAutoIncrInserter is implemented by dialects that can
|
||||||
|
// perform automatic assignment of any primary key type (i.e. strings
|
||||||
|
// for uuids, integers for serials, etc).
|
||||||
|
type TargetedAutoIncrInserter interface {
|
||||||
|
// InsertAutoIncrToTarget runs an insert operation and assigns the
|
||||||
|
// automatically generated primary key directly to the passed in
|
||||||
|
// target. The target should be a pointer to the primary key
|
||||||
|
// field of the value being inserted.
|
||||||
|
InsertAutoIncrToTarget(exec SqlExecutor, insertSql string, target interface{}, params ...interface{}) error
|
||||||
|
}
|
||||||
|
|
||||||
|
func standardInsertAutoIncr(exec SqlExecutor, insertSql string, params ...interface{}) (int64, error) {
|
||||||
|
res, err := exec.Exec(insertSql, params...)
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
return res.LastInsertId()
|
||||||
|
}
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////
|
||||||
|
// sqlite3 //
|
||||||
|
/////////////
|
||||||
|
|
||||||
|
type SqliteDialect struct {
|
||||||
|
suffix string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d SqliteDialect) QuerySuffix() string { return ";" }
|
||||||
|
|
||||||
|
func (d SqliteDialect) ToSqlType(val reflect.Type, maxsize int, isAutoIncr bool) string {
|
||||||
|
switch val.Kind() {
|
||||||
|
case reflect.Ptr:
|
||||||
|
return d.ToSqlType(val.Elem(), maxsize, isAutoIncr)
|
||||||
|
case reflect.Bool:
|
||||||
|
return "integer"
|
||||||
|
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
|
||||||
|
return "integer"
|
||||||
|
case reflect.Float64, reflect.Float32:
|
||||||
|
return "real"
|
||||||
|
case reflect.Slice:
|
||||||
|
if val.Elem().Kind() == reflect.Uint8 {
|
||||||
|
return "blob"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
switch val.Name() {
|
||||||
|
case "NullInt64":
|
||||||
|
return "integer"
|
||||||
|
case "NullFloat64":
|
||||||
|
return "real"
|
||||||
|
case "NullBool":
|
||||||
|
return "integer"
|
||||||
|
case "Time":
|
||||||
|
return "datetime"
|
||||||
|
}
|
||||||
|
|
||||||
|
if maxsize < 1 {
|
||||||
|
maxsize = 255
|
||||||
|
}
|
||||||
|
return fmt.Sprintf("varchar(%d)", maxsize)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns autoincrement
|
||||||
|
func (d SqliteDialect) AutoIncrStr() string {
|
||||||
|
return "autoincrement"
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d SqliteDialect) AutoIncrBindValue() string {
|
||||||
|
return "null"
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d SqliteDialect) AutoIncrInsertSuffix(col *ColumnMap) string {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns suffix
|
||||||
|
func (d SqliteDialect) CreateTableSuffix() string {
|
||||||
|
return d.suffix
|
||||||
|
}
|
||||||
|
|
||||||
|
// With sqlite, there technically isn't a TRUNCATE statement,
|
||||||
|
// but a DELETE FROM uses a truncate optimization:
|
||||||
|
// http://www.sqlite.org/lang_delete.html
|
||||||
|
func (d SqliteDialect) TruncateClause() string {
|
||||||
|
return "delete from"
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns "?"
|
||||||
|
func (d SqliteDialect) BindVar(i int) string {
|
||||||
|
return "?"
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d SqliteDialect) InsertAutoIncr(exec SqlExecutor, insertSql string, params ...interface{}) (int64, error) {
|
||||||
|
return standardInsertAutoIncr(exec, insertSql, params...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d SqliteDialect) QuoteField(f string) string {
|
||||||
|
return `"` + f + `"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// sqlite does not have schemas like PostgreSQL does, so just escape it like normal
|
||||||
|
func (d SqliteDialect) QuotedTableForQuery(schema string, table string) string {
|
||||||
|
return d.QuoteField(table)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d SqliteDialect) IfSchemaNotExists(command, schema string) string {
|
||||||
|
return fmt.Sprintf("%s if not exists", command)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d SqliteDialect) IfTableExists(command, schema, table string) string {
|
||||||
|
return fmt.Sprintf("%s if exists", command)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d SqliteDialect) IfTableNotExists(command, schema, table string) string {
|
||||||
|
return fmt.Sprintf("%s if not exists", command)
|
||||||
|
}
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////
|
||||||
|
// PostgreSQL //
|
||||||
|
////////////////
|
||||||
|
|
||||||
|
type PostgresDialect struct {
|
||||||
|
suffix string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d PostgresDialect) QuerySuffix() string { return ";" }
|
||||||
|
|
||||||
|
func (d PostgresDialect) ToSqlType(val reflect.Type, maxsize int, isAutoIncr bool) string {
|
||||||
|
switch val.Kind() {
|
||||||
|
case reflect.Ptr:
|
||||||
|
return d.ToSqlType(val.Elem(), maxsize, isAutoIncr)
|
||||||
|
case reflect.Bool:
|
||||||
|
return "boolean"
|
||||||
|
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Uint8, reflect.Uint16, reflect.Uint32:
|
||||||
|
if isAutoIncr {
|
||||||
|
return "serial"
|
||||||
|
}
|
||||||
|
return "integer"
|
||||||
|
case reflect.Int64, reflect.Uint64:
|
||||||
|
if isAutoIncr {
|
||||||
|
return "bigserial"
|
||||||
|
}
|
||||||
|
return "bigint"
|
||||||
|
case reflect.Float64:
|
||||||
|
return "double precision"
|
||||||
|
case reflect.Float32:
|
||||||
|
return "real"
|
||||||
|
case reflect.Slice:
|
||||||
|
if val.Elem().Kind() == reflect.Uint8 {
|
||||||
|
return "bytea"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
switch val.Name() {
|
||||||
|
case "NullInt64":
|
||||||
|
return "bigint"
|
||||||
|
case "NullFloat64":
|
||||||
|
return "double precision"
|
||||||
|
case "NullBool":
|
||||||
|
return "boolean"
|
||||||
|
case "Time":
|
||||||
|
return "timestamp with time zone"
|
||||||
|
}
|
||||||
|
|
||||||
|
if maxsize > 0 {
|
||||||
|
return fmt.Sprintf("varchar(%d)", maxsize)
|
||||||
|
} else {
|
||||||
|
return "text"
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns empty string
|
||||||
|
func (d PostgresDialect) AutoIncrStr() string {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d PostgresDialect) AutoIncrBindValue() string {
|
||||||
|
return "default"
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d PostgresDialect) AutoIncrInsertSuffix(col *ColumnMap) string {
|
||||||
|
return " returning " + col.ColumnName
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns suffix
|
||||||
|
func (d PostgresDialect) CreateTableSuffix() string {
|
||||||
|
return d.suffix
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d PostgresDialect) TruncateClause() string {
|
||||||
|
return "truncate"
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns "$(i+1)"
|
||||||
|
func (d PostgresDialect) BindVar(i int) string {
|
||||||
|
return fmt.Sprintf("$%d", i+1)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d PostgresDialect) InsertAutoIncrToTarget(exec SqlExecutor, insertSql string, target interface{}, params ...interface{}) error {
|
||||||
|
rows, err := exec.query(insertSql, params...)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer rows.Close()
|
||||||
|
|
||||||
|
if rows.Next() {
|
||||||
|
err := rows.Scan(target)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return errors.New("No serial value returned for insert: " + insertSql + " Encountered error: " + rows.Err().Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d PostgresDialect) QuoteField(f string) string {
|
||||||
|
return `"` + strings.ToLower(f) + `"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d PostgresDialect) QuotedTableForQuery(schema string, table string) string {
|
||||||
|
if strings.TrimSpace(schema) == "" {
|
||||||
|
return d.QuoteField(table)
|
||||||
|
}
|
||||||
|
|
||||||
|
return schema + "." + d.QuoteField(table)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d PostgresDialect) IfSchemaNotExists(command, schema string) string {
|
||||||
|
return fmt.Sprintf("%s if not exists", command)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d PostgresDialect) IfTableExists(command, schema, table string) string {
|
||||||
|
return fmt.Sprintf("%s if exists", command)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d PostgresDialect) IfTableNotExists(command, schema, table string) string {
|
||||||
|
return fmt.Sprintf("%s if not exists", command)
|
||||||
|
}
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////
|
||||||
|
// MySQL //
|
||||||
|
///////////
|
||||||
|
|
||||||
|
// Implementation of Dialect for MySQL databases.
|
||||||
|
type MySQLDialect struct {
|
||||||
|
|
||||||
|
// Engine is the storage engine to use "InnoDB" vs "MyISAM" for example
|
||||||
|
Engine string
|
||||||
|
|
||||||
|
// Encoding is the character encoding to use for created tables
|
||||||
|
Encoding string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d MySQLDialect) QuerySuffix() string { return ";" }
|
||||||
|
|
||||||
|
func (d MySQLDialect) ToSqlType(val reflect.Type, maxsize int, isAutoIncr bool) string {
|
||||||
|
switch val.Kind() {
|
||||||
|
case reflect.Ptr:
|
||||||
|
return d.ToSqlType(val.Elem(), maxsize, isAutoIncr)
|
||||||
|
case reflect.Bool:
|
||||||
|
return "boolean"
|
||||||
|
case reflect.Int8:
|
||||||
|
return "tinyint"
|
||||||
|
case reflect.Uint8:
|
||||||
|
return "tinyint unsigned"
|
||||||
|
case reflect.Int16:
|
||||||
|
return "smallint"
|
||||||
|
case reflect.Uint16:
|
||||||
|
return "smallint unsigned"
|
||||||
|
case reflect.Int, reflect.Int32:
|
||||||
|
return "int"
|
||||||
|
case reflect.Uint, reflect.Uint32:
|
||||||
|
return "int unsigned"
|
||||||
|
case reflect.Int64:
|
||||||
|
return "bigint"
|
||||||
|
case reflect.Uint64:
|
||||||
|
return "bigint unsigned"
|
||||||
|
case reflect.Float64, reflect.Float32:
|
||||||
|
return "double"
|
||||||
|
case reflect.Slice:
|
||||||
|
if val.Elem().Kind() == reflect.Uint8 {
|
||||||
|
return "mediumblob"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
switch val.Name() {
|
||||||
|
case "NullInt64":
|
||||||
|
return "bigint"
|
||||||
|
case "NullFloat64":
|
||||||
|
return "double"
|
||||||
|
case "NullBool":
|
||||||
|
return "tinyint"
|
||||||
|
case "Time":
|
||||||
|
return "datetime"
|
||||||
|
}
|
||||||
|
|
||||||
|
if maxsize < 1 {
|
||||||
|
maxsize = 255
|
||||||
|
}
|
||||||
|
return fmt.Sprintf("varchar(%d)", maxsize)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns auto_increment
|
||||||
|
func (d MySQLDialect) AutoIncrStr() string {
|
||||||
|
return "auto_increment"
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d MySQLDialect) AutoIncrBindValue() string {
|
||||||
|
return "null"
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d MySQLDialect) AutoIncrInsertSuffix(col *ColumnMap) string {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns engine=%s charset=%s based on values stored on struct
|
||||||
|
func (d MySQLDialect) CreateTableSuffix() string {
|
||||||
|
if d.Engine == "" || d.Encoding == "" {
|
||||||
|
msg := "gorp - undefined"
|
||||||
|
|
||||||
|
if d.Engine == "" {
|
||||||
|
msg += " MySQLDialect.Engine"
|
||||||
|
}
|
||||||
|
if d.Engine == "" && d.Encoding == "" {
|
||||||
|
msg += ","
|
||||||
|
}
|
||||||
|
if d.Encoding == "" {
|
||||||
|
msg += " MySQLDialect.Encoding"
|
||||||
|
}
|
||||||
|
msg += ". Check that your MySQLDialect was correctly initialized when declared."
|
||||||
|
panic(msg)
|
||||||
|
}
|
||||||
|
|
||||||
|
return fmt.Sprintf(" engine=%s charset=%s", d.Engine, d.Encoding)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d MySQLDialect) TruncateClause() string {
|
||||||
|
return "truncate"
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns "?"
|
||||||
|
func (d MySQLDialect) BindVar(i int) string {
|
||||||
|
return "?"
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d MySQLDialect) InsertAutoIncr(exec SqlExecutor, insertSql string, params ...interface{}) (int64, error) {
|
||||||
|
return standardInsertAutoIncr(exec, insertSql, params...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d MySQLDialect) QuoteField(f string) string {
|
||||||
|
return "`" + f + "`"
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d MySQLDialect) QuotedTableForQuery(schema string, table string) string {
|
||||||
|
if strings.TrimSpace(schema) == "" {
|
||||||
|
return d.QuoteField(table)
|
||||||
|
}
|
||||||
|
|
||||||
|
return schema + "." + d.QuoteField(table)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d MySQLDialect) IfSchemaNotExists(command, schema string) string {
|
||||||
|
return fmt.Sprintf("%s if not exists", command)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d MySQLDialect) IfTableExists(command, schema, table string) string {
|
||||||
|
return fmt.Sprintf("%s if exists", command)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d MySQLDialect) IfTableNotExists(command, schema, table string) string {
|
||||||
|
return fmt.Sprintf("%s if not exists", command)
|
||||||
|
}
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////
|
||||||
|
// Sql Server //
|
||||||
|
////////////////
|
||||||
|
|
||||||
|
// Implementation of Dialect for Microsoft SQL Server databases.
|
||||||
|
// Tested on SQL Server 2008 with driver: github.com/denisenkom/go-mssqldb
|
||||||
|
|
||||||
|
type SqlServerDialect struct {
|
||||||
|
suffix string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d SqlServerDialect) ToSqlType(val reflect.Type, maxsize int, isAutoIncr bool) string {
|
||||||
|
switch val.Kind() {
|
||||||
|
case reflect.Ptr:
|
||||||
|
return d.ToSqlType(val.Elem(), maxsize, isAutoIncr)
|
||||||
|
case reflect.Bool:
|
||||||
|
return "bit"
|
||||||
|
case reflect.Int8:
|
||||||
|
return "tinyint"
|
||||||
|
case reflect.Uint8:
|
||||||
|
return "smallint"
|
||||||
|
case reflect.Int16:
|
||||||
|
return "smallint"
|
||||||
|
case reflect.Uint16:
|
||||||
|
return "int"
|
||||||
|
case reflect.Int, reflect.Int32:
|
||||||
|
return "int"
|
||||||
|
case reflect.Uint, reflect.Uint32:
|
||||||
|
return "bigint"
|
||||||
|
case reflect.Int64:
|
||||||
|
return "bigint"
|
||||||
|
case reflect.Uint64:
|
||||||
|
return "bigint"
|
||||||
|
case reflect.Float32:
|
||||||
|
return "real"
|
||||||
|
case reflect.Float64:
|
||||||
|
return "float(53)"
|
||||||
|
case reflect.Slice:
|
||||||
|
if val.Elem().Kind() == reflect.Uint8 {
|
||||||
|
return "varbinary"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
switch val.Name() {
|
||||||
|
case "NullInt64":
|
||||||
|
return "bigint"
|
||||||
|
case "NullFloat64":
|
||||||
|
return "float(53)"
|
||||||
|
case "NullBool":
|
||||||
|
return "tinyint"
|
||||||
|
case "Time":
|
||||||
|
return "datetime"
|
||||||
|
}
|
||||||
|
|
||||||
|
if maxsize < 1 {
|
||||||
|
maxsize = 255
|
||||||
|
}
|
||||||
|
return fmt.Sprintf("varchar(%d)", maxsize)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns auto_increment
|
||||||
|
func (d SqlServerDialect) AutoIncrStr() string {
|
||||||
|
return "identity(0,1)"
|
||||||
|
}
|
||||||
|
|
||||||
|
// Empty string removes autoincrement columns from the INSERT statements.
|
||||||
|
func (d SqlServerDialect) AutoIncrBindValue() string {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d SqlServerDialect) AutoIncrInsertSuffix(col *ColumnMap) string {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns suffix
|
||||||
|
func (d SqlServerDialect) CreateTableSuffix() string {
|
||||||
|
|
||||||
|
return d.suffix
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d SqlServerDialect) TruncateClause() string {
|
||||||
|
return "delete from"
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns "?"
|
||||||
|
func (d SqlServerDialect) BindVar(i int) string {
|
||||||
|
return "?"
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d SqlServerDialect) InsertAutoIncr(exec SqlExecutor, insertSql string, params ...interface{}) (int64, error) {
|
||||||
|
return standardInsertAutoIncr(exec, insertSql, params...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d SqlServerDialect) QuoteField(f string) string {
|
||||||
|
return `"` + f + `"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d SqlServerDialect) QuotedTableForQuery(schema string, table string) string {
|
||||||
|
if strings.TrimSpace(schema) == "" {
|
||||||
|
return table
|
||||||
|
}
|
||||||
|
return schema + "." + table
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d SqlServerDialect) QuerySuffix() string { return ";" }
|
||||||
|
|
||||||
|
func (d SqlServerDialect) IfSchemaNotExists(command, schema string) string {
|
||||||
|
s := fmt.Sprintf("if not exists (select name from sys.schemas where name = '%s') %s", schema, command)
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d SqlServerDialect) IfTableExists(command, schema, table string) string {
|
||||||
|
var schema_clause string
|
||||||
|
if strings.TrimSpace(schema) != "" {
|
||||||
|
schema_clause = fmt.Sprintf("table_schema = '%s' and ", schema)
|
||||||
|
}
|
||||||
|
s := fmt.Sprintf("if exists (select * from information_schema.tables where %stable_name = '%s') %s", schema_clause, table, command)
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d SqlServerDialect) IfTableNotExists(command, schema, table string) string {
|
||||||
|
var schema_clause string
|
||||||
|
if strings.TrimSpace(schema) != "" {
|
||||||
|
schema_clause = fmt.Sprintf("table_schema = '%s' and ", schema)
|
||||||
|
}
|
||||||
|
s := fmt.Sprintf("if not exists (select * from information_schema.tables where %stable_name = '%s') %s", schema_clause, table, command)
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////
|
||||||
|
// Oracle //
|
||||||
|
///////////
|
||||||
|
|
||||||
|
// Implementation of Dialect for Oracle databases.
|
||||||
|
type OracleDialect struct{}
|
||||||
|
|
||||||
|
func (d OracleDialect) QuerySuffix() string { return "" }
|
||||||
|
|
||||||
|
func (d OracleDialect) ToSqlType(val reflect.Type, maxsize int, isAutoIncr bool) string {
|
||||||
|
switch val.Kind() {
|
||||||
|
case reflect.Ptr:
|
||||||
|
return d.ToSqlType(val.Elem(), maxsize, isAutoIncr)
|
||||||
|
case reflect.Bool:
|
||||||
|
return "boolean"
|
||||||
|
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Uint8, reflect.Uint16, reflect.Uint32:
|
||||||
|
if isAutoIncr {
|
||||||
|
return "serial"
|
||||||
|
}
|
||||||
|
return "integer"
|
||||||
|
case reflect.Int64, reflect.Uint64:
|
||||||
|
if isAutoIncr {
|
||||||
|
return "bigserial"
|
||||||
|
}
|
||||||
|
return "bigint"
|
||||||
|
case reflect.Float64:
|
||||||
|
return "double precision"
|
||||||
|
case reflect.Float32:
|
||||||
|
return "real"
|
||||||
|
case reflect.Slice:
|
||||||
|
if val.Elem().Kind() == reflect.Uint8 {
|
||||||
|
return "bytea"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
switch val.Name() {
|
||||||
|
case "NullInt64":
|
||||||
|
return "bigint"
|
||||||
|
case "NullFloat64":
|
||||||
|
return "double precision"
|
||||||
|
case "NullBool":
|
||||||
|
return "boolean"
|
||||||
|
case "NullTime", "Time":
|
||||||
|
return "timestamp with time zone"
|
||||||
|
}
|
||||||
|
|
||||||
|
if maxsize > 0 {
|
||||||
|
return fmt.Sprintf("varchar(%d)", maxsize)
|
||||||
|
} else {
|
||||||
|
return "text"
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns empty string
|
||||||
|
func (d OracleDialect) AutoIncrStr() string {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d OracleDialect) AutoIncrBindValue() string {
|
||||||
|
return "default"
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d OracleDialect) AutoIncrInsertSuffix(col *ColumnMap) string {
|
||||||
|
return " returning " + col.ColumnName
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns suffix
|
||||||
|
func (d OracleDialect) CreateTableSuffix() string {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d OracleDialect) TruncateClause() string {
|
||||||
|
return "truncate"
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns "$(i+1)"
|
||||||
|
func (d OracleDialect) BindVar(i int) string {
|
||||||
|
return fmt.Sprintf(":%d", i+1)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d OracleDialect) InsertAutoIncr(exec SqlExecutor, insertSql string, params ...interface{}) (int64, error) {
|
||||||
|
rows, err := exec.query(insertSql, params...)
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
defer rows.Close()
|
||||||
|
|
||||||
|
if rows.Next() {
|
||||||
|
var id int64
|
||||||
|
err := rows.Scan(&id)
|
||||||
|
return id, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0, errors.New("No serial value returned for insert: " + insertSql + " Encountered error: " + rows.Err().Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d OracleDialect) QuoteField(f string) string {
|
||||||
|
return `"` + strings.ToUpper(f) + `"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d OracleDialect) QuotedTableForQuery(schema string, table string) string {
|
||||||
|
if strings.TrimSpace(schema) == "" {
|
||||||
|
return d.QuoteField(table)
|
||||||
|
}
|
||||||
|
|
||||||
|
return schema + "." + d.QuoteField(table)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d OracleDialect) IfSchemaNotExists(command, schema string) string {
|
||||||
|
return fmt.Sprintf("%s if not exists", command)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d OracleDialect) IfTableExists(command, schema, table string) string {
|
||||||
|
return fmt.Sprintf("%s if exists", command)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d OracleDialect) IfTableNotExists(command, schema, table string) string {
|
||||||
|
return fmt.Sprintf("%s if not exists", command)
|
||||||
|
}
|
26
Godeps/_workspace/src/github.com/coopernurse/gorp/errors.go
generated
vendored
Normal file
26
Godeps/_workspace/src/github.com/coopernurse/gorp/errors.go
generated
vendored
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
package gorp
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
)
|
||||||
|
|
||||||
|
// A non-fatal error, when a select query returns columns that do not exist
|
||||||
|
// as fields in the struct it is being mapped to
|
||||||
|
type NoFieldInTypeError struct {
|
||||||
|
TypeName string
|
||||||
|
MissingColNames []string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (err *NoFieldInTypeError) Error() string {
|
||||||
|
return fmt.Sprintf("gorp: No fields %+v in type %s", err.MissingColNames, err.TypeName)
|
||||||
|
}
|
||||||
|
|
||||||
|
// returns true if the error is non-fatal (ie, we shouldn't immediately return)
|
||||||
|
func NonFatalError(err error) bool {
|
||||||
|
switch err.(type) {
|
||||||
|
case *NoFieldInTypeError:
|
||||||
|
return true
|
||||||
|
default:
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
2082
Godeps/_workspace/src/github.com/coopernurse/gorp/gorp.go
generated
vendored
Normal file
2082
Godeps/_workspace/src/github.com/coopernurse/gorp/gorp.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load diff
2083
Godeps/_workspace/src/github.com/coopernurse/gorp/gorp_test.go
generated
vendored
Normal file
2083
Godeps/_workspace/src/github.com/coopernurse/gorp/gorp_test.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load diff
22
Godeps/_workspace/src/github.com/coopernurse/gorp/test_all.sh
generated
vendored
Normal file
22
Godeps/_workspace/src/github.com/coopernurse/gorp/test_all.sh
generated
vendored
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
# on macs, you may need to:
|
||||||
|
# export GOBUILDFLAG=-ldflags -linkmode=external
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
export GORP_TEST_DSN=gorptest/gorptest/gorptest
|
||||||
|
export GORP_TEST_DIALECT=mysql
|
||||||
|
go test $GOBUILDFLAG .
|
||||||
|
|
||||||
|
export GORP_TEST_DSN=gorptest:gorptest@/gorptest
|
||||||
|
export GORP_TEST_DIALECT=gomysql
|
||||||
|
go test $GOBUILDFLAG .
|
||||||
|
|
||||||
|
export GORP_TEST_DSN="user=gorptest password=gorptest dbname=gorptest sslmode=disable"
|
||||||
|
export GORP_TEST_DIALECT=postgres
|
||||||
|
go test $GOBUILDFLAG .
|
||||||
|
|
||||||
|
export GORP_TEST_DSN=/tmp/gorptest.bin
|
||||||
|
export GORP_TEST_DIALECT=sqlite
|
||||||
|
go test $GOBUILDFLAG .
|
1
Godeps/_workspace/src/github.com/coreos/dex
generated
vendored
Symbolic link
1
Godeps/_workspace/src/github.com/coreos/dex
generated
vendored
Symbolic link
|
@ -0,0 +1 @@
|
||||||
|
/Users/bobbyrullo/dex
|
51
Godeps/_workspace/src/github.com/coreos/go-oidc/http/client.go
generated
vendored
Normal file
51
Godeps/_workspace/src/github.com/coreos/go-oidc/http/client.go
generated
vendored
Normal file
|
@ -0,0 +1,51 @@
|
||||||
|
package http
|
||||||
|
|
||||||
|
import (
|
||||||
|
"io/ioutil"
|
||||||
|
"net/http"
|
||||||
|
"net/http/httptest"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Client interface {
|
||||||
|
Do(*http.Request) (*http.Response, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
type HandlerClient struct {
|
||||||
|
Handler http.Handler
|
||||||
|
}
|
||||||
|
|
||||||
|
func (hc *HandlerClient) Do(r *http.Request) (*http.Response, error) {
|
||||||
|
w := httptest.NewRecorder()
|
||||||
|
hc.Handler.ServeHTTP(w, r)
|
||||||
|
|
||||||
|
resp := http.Response{
|
||||||
|
StatusCode: w.Code,
|
||||||
|
Header: w.Header(),
|
||||||
|
Body: ioutil.NopCloser(w.Body),
|
||||||
|
}
|
||||||
|
|
||||||
|
return &resp, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type RequestRecorder struct {
|
||||||
|
Response *http.Response
|
||||||
|
Error error
|
||||||
|
|
||||||
|
Request *http.Request
|
||||||
|
}
|
||||||
|
|
||||||
|
func (rr *RequestRecorder) Do(req *http.Request) (*http.Response, error) {
|
||||||
|
rr.Request = req
|
||||||
|
|
||||||
|
if rr.Response == nil && rr.Error == nil {
|
||||||
|
panic("RequestRecorder Response and Error cannot both be nil")
|
||||||
|
} else if rr.Response != nil && rr.Error != nil {
|
||||||
|
panic("RequestRecorder Response and Error cannot both be non-nil")
|
||||||
|
}
|
||||||
|
|
||||||
|
return rr.Response, rr.Error
|
||||||
|
}
|
||||||
|
|
||||||
|
func (rr *RequestRecorder) RoundTrip(req *http.Request) (*http.Response, error) {
|
||||||
|
return rr.Do(req)
|
||||||
|
}
|
159
Godeps/_workspace/src/github.com/coreos/go-oidc/http/http.go
generated
vendored
Normal file
159
Godeps/_workspace/src/github.com/coreos/go-oidc/http/http.go
generated
vendored
Normal file
|
@ -0,0 +1,159 @@
|
||||||
|
package http
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/base64"
|
||||||
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
|
"net/http"
|
||||||
|
"net/url"
|
||||||
|
"path"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/coreos/pkg/capnslog"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
log = capnslog.NewPackageLogger("github.com/coreos/go-oidc", "http")
|
||||||
|
)
|
||||||
|
|
||||||
|
func WriteError(w http.ResponseWriter, code int, msg string) {
|
||||||
|
e := struct {
|
||||||
|
Error string `json:"error"`
|
||||||
|
}{
|
||||||
|
Error: msg,
|
||||||
|
}
|
||||||
|
b, err := json.Marshal(e)
|
||||||
|
if err != nil {
|
||||||
|
log.Errorf("Failed marshaling %#v to JSON: %v", e, err)
|
||||||
|
}
|
||||||
|
w.Header().Set("Content-Type", "application/json")
|
||||||
|
w.WriteHeader(code)
|
||||||
|
w.Write(b)
|
||||||
|
}
|
||||||
|
|
||||||
|
// BasicAuth parses a username and password from the request's
|
||||||
|
// Authorization header. This was pulled from golang master:
|
||||||
|
// https://codereview.appspot.com/76540043
|
||||||
|
func BasicAuth(r *http.Request) (username, password string, ok bool) {
|
||||||
|
auth := r.Header.Get("Authorization")
|
||||||
|
if auth == "" {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if !strings.HasPrefix(auth, "Basic ") {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
c, err := base64.StdEncoding.DecodeString(strings.TrimPrefix(auth, "Basic "))
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
cs := string(c)
|
||||||
|
s := strings.IndexByte(cs, ':')
|
||||||
|
if s < 0 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
return cs[:s], cs[s+1:], true
|
||||||
|
}
|
||||||
|
|
||||||
|
func cacheControlMaxAge(hdr string) (time.Duration, bool, error) {
|
||||||
|
for _, field := range strings.Split(hdr, ",") {
|
||||||
|
parts := strings.SplitN(strings.TrimSpace(field), "=", 2)
|
||||||
|
k := strings.ToLower(strings.TrimSpace(parts[0]))
|
||||||
|
if k != "max-age" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(parts) == 1 {
|
||||||
|
return 0, false, errors.New("max-age has no value")
|
||||||
|
}
|
||||||
|
|
||||||
|
v := strings.TrimSpace(parts[1])
|
||||||
|
if v == "" {
|
||||||
|
return 0, false, errors.New("max-age has empty value")
|
||||||
|
}
|
||||||
|
|
||||||
|
age, err := strconv.Atoi(v)
|
||||||
|
if err != nil {
|
||||||
|
return 0, false, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if age <= 0 {
|
||||||
|
return 0, false, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return time.Duration(age) * time.Second, true, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0, false, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func expires(date, expires string) (time.Duration, bool, error) {
|
||||||
|
if date == "" || expires == "" {
|
||||||
|
return 0, false, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
te, err := time.Parse(time.RFC1123, expires)
|
||||||
|
if err != nil {
|
||||||
|
return 0, false, err
|
||||||
|
}
|
||||||
|
|
||||||
|
td, err := time.Parse(time.RFC1123, date)
|
||||||
|
if err != nil {
|
||||||
|
return 0, false, err
|
||||||
|
}
|
||||||
|
|
||||||
|
ttl := te.Sub(td)
|
||||||
|
|
||||||
|
// headers indicate data already expired, caller should not
|
||||||
|
// have to care about this case
|
||||||
|
if ttl <= 0 {
|
||||||
|
return 0, false, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return ttl, true, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func Cacheable(hdr http.Header) (time.Duration, bool, error) {
|
||||||
|
ttl, ok, err := cacheControlMaxAge(hdr.Get("Cache-Control"))
|
||||||
|
if err != nil || ok {
|
||||||
|
return ttl, ok, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return expires(hdr.Get("Date"), hdr.Get("Expires"))
|
||||||
|
}
|
||||||
|
|
||||||
|
// MergeQuery appends additional query values to an existing URL.
|
||||||
|
func MergeQuery(u url.URL, q url.Values) url.URL {
|
||||||
|
uv := u.Query()
|
||||||
|
for k, vs := range q {
|
||||||
|
for _, v := range vs {
|
||||||
|
uv.Add(k, v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
u.RawQuery = uv.Encode()
|
||||||
|
return u
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewResourceLocation appends a resource id to the end of the requested URL path.
|
||||||
|
func NewResourceLocation(reqURL *url.URL, id string) string {
|
||||||
|
var u url.URL
|
||||||
|
u = *reqURL
|
||||||
|
u.Path = path.Join(u.Path, id)
|
||||||
|
u.RawQuery = ""
|
||||||
|
u.Fragment = ""
|
||||||
|
return u.String()
|
||||||
|
}
|
||||||
|
|
||||||
|
// CopyRequest returns a clone of the provided *http.Request.
|
||||||
|
// The returned object is a shallow copy of the struct and a
|
||||||
|
// deep copy of its Header field.
|
||||||
|
func CopyRequest(r *http.Request) *http.Request {
|
||||||
|
r2 := *r
|
||||||
|
r2.Header = make(http.Header)
|
||||||
|
for k, s := range r.Header {
|
||||||
|
r2.Header[k] = s
|
||||||
|
}
|
||||||
|
return &r2
|
||||||
|
}
|
380
Godeps/_workspace/src/github.com/coreos/go-oidc/http/http_test.go
generated
vendored
Normal file
380
Godeps/_workspace/src/github.com/coreos/go-oidc/http/http_test.go
generated
vendored
Normal file
|
@ -0,0 +1,380 @@
|
||||||
|
package http
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
"net/url"
|
||||||
|
"reflect"
|
||||||
|
"strings"
|
||||||
|
"testing"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestCacheControlMaxAgeSuccess(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
hdr string
|
||||||
|
wantAge time.Duration
|
||||||
|
wantOK bool
|
||||||
|
}{
|
||||||
|
{"max-age=12", 12 * time.Second, true},
|
||||||
|
{"max-age=-12", 0, false},
|
||||||
|
{"max-age=0", 0, false},
|
||||||
|
{"public, max-age=12", 12 * time.Second, true},
|
||||||
|
{"public, max-age=40192, must-revalidate", 40192 * time.Second, true},
|
||||||
|
{"public, not-max-age=12, must-revalidate", time.Duration(0), false},
|
||||||
|
}
|
||||||
|
|
||||||
|
for i, tt := range tests {
|
||||||
|
maxAge, ok, err := cacheControlMaxAge(tt.hdr)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("case %d: err=%v", i, err)
|
||||||
|
}
|
||||||
|
if tt.wantAge != maxAge {
|
||||||
|
t.Errorf("case %d: want=%d got=%d", i, tt.wantAge, maxAge)
|
||||||
|
}
|
||||||
|
if tt.wantOK != ok {
|
||||||
|
t.Errorf("case %d: incorrect ok value: want=%t got=%t", i, tt.wantOK, ok)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCacheControlMaxAgeFail(t *testing.T) {
|
||||||
|
tests := []string{
|
||||||
|
"max-age=aasdf",
|
||||||
|
"max-age=",
|
||||||
|
"max-age",
|
||||||
|
}
|
||||||
|
|
||||||
|
for i, tt := range tests {
|
||||||
|
_, ok, err := cacheControlMaxAge(tt)
|
||||||
|
if ok {
|
||||||
|
t.Errorf("case %d: want ok=false, got true", i)
|
||||||
|
}
|
||||||
|
if err == nil {
|
||||||
|
t.Errorf("case %d: want non-nil err", i)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestMergeQuery(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
u string
|
||||||
|
q url.Values
|
||||||
|
w string
|
||||||
|
}{
|
||||||
|
// No values
|
||||||
|
{
|
||||||
|
u: "http://example.com",
|
||||||
|
q: nil,
|
||||||
|
w: "http://example.com",
|
||||||
|
},
|
||||||
|
// No additional values
|
||||||
|
{
|
||||||
|
u: "http://example.com?foo=bar",
|
||||||
|
q: nil,
|
||||||
|
w: "http://example.com?foo=bar",
|
||||||
|
},
|
||||||
|
// Simple addition
|
||||||
|
{
|
||||||
|
u: "http://example.com",
|
||||||
|
q: url.Values{
|
||||||
|
"foo": []string{"bar"},
|
||||||
|
},
|
||||||
|
w: "http://example.com?foo=bar",
|
||||||
|
},
|
||||||
|
// Addition with existing values
|
||||||
|
{
|
||||||
|
u: "http://example.com?dog=boo",
|
||||||
|
q: url.Values{
|
||||||
|
"foo": []string{"bar"},
|
||||||
|
},
|
||||||
|
w: "http://example.com?dog=boo&foo=bar",
|
||||||
|
},
|
||||||
|
// Merge
|
||||||
|
{
|
||||||
|
u: "http://example.com?dog=boo",
|
||||||
|
q: url.Values{
|
||||||
|
"dog": []string{"elroy"},
|
||||||
|
},
|
||||||
|
w: "http://example.com?dog=boo&dog=elroy",
|
||||||
|
},
|
||||||
|
// Add and merge
|
||||||
|
{
|
||||||
|
u: "http://example.com?dog=boo",
|
||||||
|
q: url.Values{
|
||||||
|
"dog": []string{"elroy"},
|
||||||
|
"foo": []string{"bar"},
|
||||||
|
},
|
||||||
|
w: "http://example.com?dog=boo&dog=elroy&foo=bar",
|
||||||
|
},
|
||||||
|
// Multivalue merge
|
||||||
|
{
|
||||||
|
u: "http://example.com?dog=boo",
|
||||||
|
q: url.Values{
|
||||||
|
"dog": []string{"elroy", "penny"},
|
||||||
|
},
|
||||||
|
w: "http://example.com?dog=boo&dog=elroy&dog=penny",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for i, tt := range tests {
|
||||||
|
ur, err := url.Parse(tt.u)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("case %d: failed parsing test url: %v, error: %v", i, tt.u, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
got := MergeQuery(*ur, tt.q)
|
||||||
|
want, err := url.Parse(tt.w)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("case %d: failed parsing want url: %v, error: %v", i, tt.w, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if !reflect.DeepEqual(*want, got) {
|
||||||
|
t.Errorf("case %d: want: %v, got: %v", i, *want, got)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestExpiresPass(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
date string
|
||||||
|
exp string
|
||||||
|
wantTTL time.Duration
|
||||||
|
wantOK bool
|
||||||
|
}{
|
||||||
|
// Expires and Date properly set
|
||||||
|
{
|
||||||
|
date: "Thu, 01 Dec 1983 22:00:00 GMT",
|
||||||
|
exp: "Fri, 02 Dec 1983 01:00:00 GMT",
|
||||||
|
wantTTL: 10800 * time.Second,
|
||||||
|
wantOK: true,
|
||||||
|
},
|
||||||
|
// empty headers
|
||||||
|
{
|
||||||
|
date: "",
|
||||||
|
exp: "",
|
||||||
|
wantOK: false,
|
||||||
|
},
|
||||||
|
// lack of Expirs short-ciruits Date parsing
|
||||||
|
{
|
||||||
|
date: "foo",
|
||||||
|
exp: "",
|
||||||
|
wantOK: false,
|
||||||
|
},
|
||||||
|
// lack of Date short-ciruits Expires parsing
|
||||||
|
{
|
||||||
|
date: "",
|
||||||
|
exp: "foo",
|
||||||
|
wantOK: false,
|
||||||
|
},
|
||||||
|
// no Date
|
||||||
|
{
|
||||||
|
exp: "Thu, 01 Dec 1983 22:00:00 GMT",
|
||||||
|
wantTTL: 0,
|
||||||
|
wantOK: false,
|
||||||
|
},
|
||||||
|
// no Expires
|
||||||
|
{
|
||||||
|
date: "Thu, 01 Dec 1983 22:00:00 GMT",
|
||||||
|
wantTTL: 0,
|
||||||
|
wantOK: false,
|
||||||
|
},
|
||||||
|
// Expires < Date
|
||||||
|
{
|
||||||
|
date: "Fri, 02 Dec 1983 01:00:00 GMT",
|
||||||
|
exp: "Thu, 01 Dec 1983 22:00:00 GMT",
|
||||||
|
wantTTL: 0,
|
||||||
|
wantOK: false,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for i, tt := range tests {
|
||||||
|
ttl, ok, err := expires(tt.date, tt.exp)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("case %d: err=%v", i, err)
|
||||||
|
}
|
||||||
|
if tt.wantTTL != ttl {
|
||||||
|
t.Errorf("case %d: want=%d got=%d", i, tt.wantTTL, ttl)
|
||||||
|
}
|
||||||
|
if tt.wantOK != ok {
|
||||||
|
t.Errorf("case %d: incorrect ok value: want=%t got=%t", i, tt.wantOK, ok)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestExpiresFail(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
date string
|
||||||
|
exp string
|
||||||
|
}{
|
||||||
|
// malformed Date header
|
||||||
|
{
|
||||||
|
date: "foo",
|
||||||
|
exp: "Fri, 02 Dec 1983 01:00:00 GMT",
|
||||||
|
},
|
||||||
|
// malformed exp header
|
||||||
|
{
|
||||||
|
date: "Fri, 02 Dec 1983 01:00:00 GMT",
|
||||||
|
exp: "bar",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for i, tt := range tests {
|
||||||
|
_, _, err := expires(tt.date, tt.exp)
|
||||||
|
if err == nil {
|
||||||
|
t.Errorf("case %d: expected non-nil error", i)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCacheablePass(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
headers http.Header
|
||||||
|
wantTTL time.Duration
|
||||||
|
wantOK bool
|
||||||
|
}{
|
||||||
|
// valid Cache-Control
|
||||||
|
{
|
||||||
|
headers: http.Header{
|
||||||
|
"Cache-Control": []string{"max-age=100"},
|
||||||
|
},
|
||||||
|
wantTTL: 100 * time.Second,
|
||||||
|
wantOK: true,
|
||||||
|
},
|
||||||
|
// valid Date/Expires
|
||||||
|
{
|
||||||
|
headers: http.Header{
|
||||||
|
"Date": []string{"Thu, 01 Dec 1983 22:00:00 GMT"},
|
||||||
|
"Expires": []string{"Fri, 02 Dec 1983 01:00:00 GMT"},
|
||||||
|
},
|
||||||
|
wantTTL: 10800 * time.Second,
|
||||||
|
wantOK: true,
|
||||||
|
},
|
||||||
|
// Cache-Control supersedes Date/Expires
|
||||||
|
{
|
||||||
|
headers: http.Header{
|
||||||
|
"Cache-Control": []string{"max-age=100"},
|
||||||
|
"Date": []string{"Thu, 01 Dec 1983 22:00:00 GMT"},
|
||||||
|
"Expires": []string{"Fri, 02 Dec 1983 01:00:00 GMT"},
|
||||||
|
},
|
||||||
|
wantTTL: 100 * time.Second,
|
||||||
|
wantOK: true,
|
||||||
|
},
|
||||||
|
// no caching headers
|
||||||
|
{
|
||||||
|
headers: http.Header{},
|
||||||
|
wantOK: false,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for i, tt := range tests {
|
||||||
|
ttl, ok, err := Cacheable(tt.headers)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("case %d: err=%v", i, err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if tt.wantTTL != ttl {
|
||||||
|
t.Errorf("case %d: want=%d got=%d", i, tt.wantTTL, ttl)
|
||||||
|
}
|
||||||
|
if tt.wantOK != ok {
|
||||||
|
t.Errorf("case %d: incorrect ok value: want=%t got=%t", i, tt.wantOK, ok)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCacheableFail(t *testing.T) {
|
||||||
|
tests := []http.Header{
|
||||||
|
// invalid Cache-Control short-circuits
|
||||||
|
http.Header{
|
||||||
|
"Cache-Control": []string{"max-age"},
|
||||||
|
"Date": []string{"Thu, 01 Dec 1983 22:00:00 GMT"},
|
||||||
|
"Expires": []string{"Fri, 02 Dec 1983 01:00:00 GMT"},
|
||||||
|
},
|
||||||
|
// no Cache-Control, invalid Expires
|
||||||
|
http.Header{
|
||||||
|
"Date": []string{"Thu, 01 Dec 1983 22:00:00 GMT"},
|
||||||
|
"Expires": []string{"boo"},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for i, tt := range tests {
|
||||||
|
_, _, err := Cacheable(tt)
|
||||||
|
if err == nil {
|
||||||
|
t.Errorf("case %d: want non-nil err", i)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestNewResourceLocation(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
ru *url.URL
|
||||||
|
id string
|
||||||
|
want string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
ru: &url.URL{
|
||||||
|
Scheme: "http",
|
||||||
|
Host: "example.com",
|
||||||
|
},
|
||||||
|
id: "foo",
|
||||||
|
want: "http://example.com/foo",
|
||||||
|
},
|
||||||
|
// https
|
||||||
|
{
|
||||||
|
ru: &url.URL{
|
||||||
|
Scheme: "https",
|
||||||
|
Host: "example.com",
|
||||||
|
},
|
||||||
|
id: "foo",
|
||||||
|
want: "https://example.com/foo",
|
||||||
|
},
|
||||||
|
// with path
|
||||||
|
{
|
||||||
|
ru: &url.URL{
|
||||||
|
Scheme: "http",
|
||||||
|
Host: "example.com",
|
||||||
|
Path: "one/two/three",
|
||||||
|
},
|
||||||
|
id: "foo",
|
||||||
|
want: "http://example.com/one/two/three/foo",
|
||||||
|
},
|
||||||
|
// with fragment
|
||||||
|
{
|
||||||
|
ru: &url.URL{
|
||||||
|
Scheme: "http",
|
||||||
|
Host: "example.com",
|
||||||
|
Fragment: "frag",
|
||||||
|
},
|
||||||
|
id: "foo",
|
||||||
|
want: "http://example.com/foo",
|
||||||
|
},
|
||||||
|
// with query
|
||||||
|
{
|
||||||
|
ru: &url.URL{
|
||||||
|
Scheme: "http",
|
||||||
|
Host: "example.com",
|
||||||
|
RawQuery: "dog=elroy",
|
||||||
|
},
|
||||||
|
id: "foo",
|
||||||
|
want: "http://example.com/foo",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for i, tt := range tests {
|
||||||
|
got := NewResourceLocation(tt.ru, tt.id)
|
||||||
|
if tt.want != got {
|
||||||
|
t.Errorf("case %d: want=%s, got=%s", i, tt.want, got)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCopyRequest(t *testing.T) {
|
||||||
|
r1, err := http.NewRequest("GET", "http://example.com", strings.NewReader("foo"))
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Unexpected error: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
r2 := CopyRequest(r1)
|
||||||
|
if !reflect.DeepEqual(r1, r2) {
|
||||||
|
t.Fatalf("Result of CopyRequest incorrect: %#v != %#v", r1, r2)
|
||||||
|
}
|
||||||
|
}
|
14
Godeps/_workspace/src/github.com/coreos/go-oidc/http/middleware.go
generated
vendored
Normal file
14
Godeps/_workspace/src/github.com/coreos/go-oidc/http/middleware.go
generated
vendored
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
package http
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
)
|
||||||
|
|
||||||
|
type LoggingMiddleware struct {
|
||||||
|
Next http.Handler
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *LoggingMiddleware) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||||
|
log.Infof("HTTP %s %v", r.Method, r.URL)
|
||||||
|
l.Next.ServeHTTP(w, r)
|
||||||
|
}
|
29
Godeps/_workspace/src/github.com/coreos/go-oidc/http/url.go
generated
vendored
Normal file
29
Godeps/_workspace/src/github.com/coreos/go-oidc/http/url.go
generated
vendored
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
package http
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"net/url"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ParseNonEmptyURL checks that a string is a parsable URL which is also not empty
|
||||||
|
// since `url.Parse("")` does not return an error. Must contian a scheme and a host.
|
||||||
|
func ParseNonEmptyURL(u string) (*url.URL, error) {
|
||||||
|
if u == "" {
|
||||||
|
return nil, errors.New("url is empty")
|
||||||
|
}
|
||||||
|
|
||||||
|
ur, err := url.Parse(u)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if ur.Scheme == "" {
|
||||||
|
return nil, errors.New("url scheme is empty")
|
||||||
|
}
|
||||||
|
|
||||||
|
if ur.Host == "" {
|
||||||
|
return nil, errors.New("url host is empty")
|
||||||
|
}
|
||||||
|
|
||||||
|
return ur, nil
|
||||||
|
}
|
49
Godeps/_workspace/src/github.com/coreos/go-oidc/http/url_test.go
generated
vendored
Normal file
49
Godeps/_workspace/src/github.com/coreos/go-oidc/http/url_test.go
generated
vendored
Normal file
|
@ -0,0 +1,49 @@
|
||||||
|
package http
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/url"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestParseNonEmptyURL(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
u string
|
||||||
|
ok bool
|
||||||
|
}{
|
||||||
|
{"", false},
|
||||||
|
{"http://", false},
|
||||||
|
{"example.com", false},
|
||||||
|
{"example", false},
|
||||||
|
{"http://example", true},
|
||||||
|
{"http://example:1234", true},
|
||||||
|
{"http://example.com", true},
|
||||||
|
{"http://example.com:1234", true},
|
||||||
|
}
|
||||||
|
|
||||||
|
for i, tt := range tests {
|
||||||
|
u, err := ParseNonEmptyURL(tt.u)
|
||||||
|
if err != nil {
|
||||||
|
t.Logf("err: %v", err)
|
||||||
|
if tt.ok {
|
||||||
|
t.Errorf("case %d: unexpected error: %v", i, err)
|
||||||
|
} else {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if !tt.ok {
|
||||||
|
t.Errorf("case %d: expected error but got none", i)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
uu, err := url.Parse(tt.u)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("case %d: unexpected error: %v", i, err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if uu.String() != u.String() {
|
||||||
|
t.Errorf("case %d: incorrect url value, want: %q, got: %q", i, uu.String(), u.String())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
79
Godeps/_workspace/src/github.com/coreos/go-oidc/jose/claims.go
generated
vendored
Normal file
79
Godeps/_workspace/src/github.com/coreos/go-oidc/jose/claims.go
generated
vendored
Normal file
|
@ -0,0 +1,79 @@
|
||||||
|
package jose
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Claims map[string]interface{}
|
||||||
|
|
||||||
|
func (c Claims) Add(name string, value interface{}) {
|
||||||
|
c[name] = value
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c Claims) StringClaim(name string) (string, bool, error) {
|
||||||
|
cl, ok := c[name]
|
||||||
|
if !ok {
|
||||||
|
return "", false, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
v, ok := cl.(string)
|
||||||
|
if !ok {
|
||||||
|
return "", false, fmt.Errorf("unable to parse claim as string: %v", name)
|
||||||
|
}
|
||||||
|
|
||||||
|
return v, true, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c Claims) Int64Claim(name string) (int64, bool, error) {
|
||||||
|
cl, ok := c[name]
|
||||||
|
if !ok {
|
||||||
|
return 0, false, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
v, ok := cl.(int64)
|
||||||
|
if !ok {
|
||||||
|
vf, ok := cl.(float64)
|
||||||
|
if !ok {
|
||||||
|
return 0, false, fmt.Errorf("unable to parse claim as int64: %v", name)
|
||||||
|
}
|
||||||
|
v = int64(vf)
|
||||||
|
}
|
||||||
|
|
||||||
|
return v, true, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c Claims) TimeClaim(name string) (time.Time, bool, error) {
|
||||||
|
v, ok, err := c.Int64Claim(name)
|
||||||
|
if !ok || err != nil {
|
||||||
|
return time.Time{}, ok, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return time.Unix(v, 0).UTC(), true, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func decodeClaims(payload []byte) (Claims, error) {
|
||||||
|
var c Claims
|
||||||
|
if err := json.Unmarshal(payload, &c); err != nil {
|
||||||
|
return nil, fmt.Errorf("malformed JWT claims, unable to decode: %v", err)
|
||||||
|
}
|
||||||
|
return c, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func marshalClaims(c Claims) ([]byte, error) {
|
||||||
|
b, err := json.Marshal(c)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return b, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func encodeClaims(c Claims) (string, error) {
|
||||||
|
b, err := marshalClaims(c)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
return encodeSegment(b), nil
|
||||||
|
}
|
Some files were not shown because too many files have changed in this diff Show more
Reference in a new issue