Esempio n. 1
0
func TestEnclosureBasic(t *testing.T) {

	var testdata = []testEnclosure{
		{`<enclosure url="http://www.scripting.com/mp3s/weatherReportSuite.mp3" length="12216320" type="audio/mpeg" />`,
			nil,
			NewTestEnclosure("http://www.scripting.com/mp3s/weatherReportSuite.mp3", "12216320", "audio/mpeg"),
		},
		{`<enclosure length="12216320" type="audio/mpeg" />`,
			xmlutils.NewError(MissingAttribute, ""),
			NewTestEnclosure("", "12216320", "audio/mpeg"),
		},
		{`<enclosure url="http://www.scripting.com/mp3s/weatherReportSuite.mp3" type="audio/mpeg" />`,
			xmlutils.NewError(MissingAttribute, ""),
			NewTestEnclosure("http://www.scripting.com/mp3s/weatherReportSuite.mp3", "", "audio/mpeg"),
		},
		{`<enclosure url="http://www.scripting.com/mp3s/weatherReportSuite.mp3" length="12216320" />`,
			xmlutils.NewError(MissingAttribute, ""),
			NewTestEnclosure("http://www.scripting.com/mp3s/weatherReportSuite.mp3", "12216320", ""),
		},
	}

	nbErrors := 0
	len := len(testdata)
	for _, testenclosure := range testdata {
		testcase := _TestEnclosureToTestVisitor(testenclosure)

		if err := testcase.CheckTestCase(); err != nil {
			t.Errorf("FAIL\n%s\nXML:\n %s\n", err, testcase.XML)
			nbErrors++
		}
	}

	t.Logf("PASS RATIO = %v/%v\n", len-nbErrors, len)
}
Esempio n. 2
0
File: entry.go Progetto: apognu/xml
func (e *Entry) validateLinks(err *utils.ErrorAggregator) {
	combinations := make([]string, 0)
	hasAlternateRel := false

	for _, link := range e.Links {
		if link.Rel.Value == "alternate" {
			hasAlternateRel = true
			s := link.Type.Value + link.HrefLang.Value
			unique := true

			for _, comb := range combinations {
				if s == comb {
					err.NewError(xmlutils.NewError(LinkAlternateDuplicated, fmt.Sprintf("Alternate Link duplicated: hreflang '%s' type '%s'", link.HrefLang.Value, link.Type.Value)))
					unique = false
				}
			}

			if unique {
				combinations = append(combinations, s)
			}
		}
	}

	if e.Occurences.Count("content") == 0 && !hasAlternateRel {
		err.NewError(xmlutils.NewError(NoContentOrAlternateLink, "Entry should have either a Content element or a Link with alternate type"))
	}
}
Esempio n. 3
0
func TestDateBasic(t *testing.T) {

	var testdata = []testDate{
		{`<updated>Tue, 20 Sep 2010 16:02:50 GMT</updated>`,
			nil,
			NewTestDate("Tue, 20 Sep 2010 16:02:50 GMT"),
		},
		{`<updated>Tue, 20 Sep 2010 16:02:50</updated>`,
			xmlutils.NewError(DateFormat, ""),
			NewTestDate("0"),
		},
		{`<updated>2003-12-13T18:30:02.25</updated>`,
			xmlutils.NewError(DateFormat, ""),
			NewTestDate("0"),
		},
	}
	nbErrors := 0
	len := len(testdata)
	for _, testdate := range testdata {
		testcase := testDateToTestVisitor(testdate)

		if err := testcase.CheckTestCase(); err != nil {
			t.Errorf("FAIL\n%s\nXML:\n %s\n", err, testcase.XML)
			nbErrors++
		}
	}

	t.Logf("PASS RATIO = %v/%v\n", len-nbErrors, len)
}
Esempio n. 4
0
func TestIdBasic(t *testing.T) {

	var testdata = []testId{
		{`<id xml:lang="en-us" xml:base="http://yo.com">https://www.yo.com</id>`,
			nil,
			IdWithBaseLang(NewTestId("https://www.yo.com"), "en-us", "http://yo.com"),
		},
		{`<id>https://www.yo.com</id>`,
			nil,
			NewTestId("https://www.yo.com"),
		},
		{`<id>https://www.%yo.com</id>`,
			xmlutils.NewError(IriNotAbsolute, ""),
			NewTestId("https://www.%yo.com"),
		},
		{`<id>
      https://www.%yo.com
     </id>`,
			xmlutils.NewError(IriNotAbsolute, ""),
			NewTestId("https://www.%yo.com"),
		},
	}
	nbErrors := 0
	len := len(testdata)
	for _, testid := range testdata {
		testcase := testIdToTestVisitor(testid)

		if err := testcase.CheckTestCase(); err != nil {
			t.Errorf("FAIL\n%s\nXML:\n %s\n", err, testcase.XML)
			nbErrors++
		}
	}

	t.Logf("PASS RATIO = %v/%v\n", len-nbErrors, len)
}
Esempio n. 5
0
func (i *InlineXHTMLContent) ProcessEndElement(el xml.EndElement) (xmlutils.Visitor, xmlutils.ParserError) {
	level := i.depth.Up()
	if level == xmlutils.RootLevel {

		if err := i.EncodeXHTMLToken(el); err != nil {
			return i, xmlutils.NewError(XHTMLEncodeToStringError, "cannot encode XHTML")
		}

		if err := i.flush(); err != nil {
			return i, err
		}

		i.completed = true

		return i, nil
	}

	if level == xmlutils.ParentLevel {
		if err := i.flush(); err != nil {
			return i.Parent, err
		}

		if i.Parent != nil {
			return i.Parent.ProcessEndElement(el)
		}
		return nil, nil
	}

	if err := i.EncodeXHTMLToken(el); err != nil {
		return i, xmlutils.NewError(XHTMLEncodeToStringError, "cannot encode XHTML")
	}

	return i, nil
}
Esempio n. 6
0
File: feed.go Progetto: apognu/xml
func (f *Feed) validateLinks(err *utils.ErrorAggregator) {
	combinations := make([]string, 0)
	hasSelf := false

	for _, link := range f.Links {
		if link.Rel.Value == "alternate" {
			s := link.Type.Value + link.HrefLang.Value
			unique := true

			for _, comb := range combinations {
				if s == comb {
					err.NewError(xmlutils.NewError(LinkAlternateDuplicated, fmt.Sprintf("Alternate Link duplicated: hreflang '%s' type '%s'", link.HrefLang.Value, link.Type.Value)))
					unique = false
				}
			}

			if unique {
				combinations = append(combinations, s)
			}
		} else if link.Rel.Value == "self" {
			hasSelf = true
		}
	}

	if !hasSelf {
		err.NewError(xmlutils.NewError(MissingSelfLink, "Feed must have a link with rel attribute set to 'self'"))
	}
}
Esempio n. 7
0
func TestGeneratorBasic(t *testing.T) {

	var testdata = []testGenerator{
		{`<generator uri="http://there.com" version="4.0" xml:lang="en-us" xml:base="http://yo.com">my generator</generator>`,
			nil,
			GeneratorWithBaseLang(NewTestGenerator("4.0", "http://there.com", "my generator"), "en-us", "http://yo.com"),
		},
		{`<generator uri="http://there.com" version="4.0">my generator</generator>`,
			nil,
			NewTestGenerator("4.0", "http://there.com", "my generator"),
		},
		{`<generator uri="http://there.com" version="4.0"><name>CHILD</name></generator>`,
			xmlutils.NewError(LeafElementHasChild, ""),
			NewTestGenerator("4.0", "http://there.com", "CHILD"),
		},
		{`<generator uri="http://%there.com" version="4.0">my generator</generator>`,
			xmlutils.NewError(IriNotValid, ""),
			NewTestGenerator("4.0", "http://%there.com", "my generator"),
		},
	}
	nbErrors := 0
	len := len(testdata)
	for _, testgenerator := range testdata {
		testcase := testGeneratorToTestVisitor(testgenerator)

		if err := testcase.CheckTestCase(); err != nil {
			t.Errorf("FAIL\n%s\nXML:\n %s\n", err, testcase.XML)
			nbErrors++
		}
	}

	t.Logf("PASS RATIO = %v/%v\n", len-nbErrors, len)
}
Esempio n. 8
0
File: link.go Progetto: apognu/xml
func (u *Updated) Validate() xmlutils.ParserError {
	errAgg := utils.NewErrorAggregator()
	link, ok := u.Parent.(*atom.Link)
	if !ok {
		errAgg.NewError(xmlutils.NewError(NotInLinkElement, "updated attr should be placed in link element"))

	} else {
		if link.Rel.String() != "replies" {
			errAgg.NewError(xmlutils.NewError(LinkNotReplies, "link element should avec a 'replies' rel for this extension"))
		}
	}

	return errAgg.ErrorObject()
}
Esempio n. 9
0
func relIsIANA(name, s string) xmlutils.ParserError {
	if s == "alternate" || s == "related" || s == "self" || s == "enclosure" || s == "via" {
		return nil
	}

	return xmlutils.NewError(RelNotValid, fmt.Sprintf("rel is not valid: %s", s))
}
Esempio n. 10
0
func contentTypeIsValid(name, s string) xmlutils.ParserError {
	if s == "text" || s == "html" || s == "xhtml" {
		return xmlutils.NewError(ContentTypeIsNotValid, "type not valid")
	}

	return nil
}
Esempio n. 11
0
func (i *InlineOtherContent) ProcessStartElement(el xmlutils.StartElement) (xmlutils.Visitor, xmlutils.ParserError) {
	err := utils.NewErrorAggregator()

	if i.depth.IsRoot() {
		for _, attr := range el.Attr {
			switch attr.Name.Local {
			case "type":
				i.Type.Value = attr.Value
				i.Type.IncOccurence()

			}
		}

	} else {
		if error := i.Encoder.EncodeToken(el); error != nil {
			err.NewError(xmlutils.NewError(XHTMLEncodeToStringError, "cannot encode XHTML"))
		}
		if i.depth.Level > 0 {
			i.hasChild = true
		}
	}

	i.depth.Down()

	return i, nil
}
Esempio n. 12
0
func TestLogoBasic(t *testing.T) {

	var testdata = []testLogo{
		{`<logo xml:lang="en-us" xml:base="http://yo.com">https://www.yo.com</logo>`,
			nil,
			LogoWithBaseLang(NewTestLogo("https://www.yo.com"), "en-us", "http://yo.com"),
		},
		{`<logo>https://www.yo.com</logo>`,
			nil,
			NewTestLogo("https://www.yo.com"),
		},
		{`<logo>https://www.%yo.com</logo>`,
			xmlutils.NewError(IriNotValid, ""),
			NewTestLogo("https://www.%yo.com"),
		},
	}
	nbErrors := 0
	len := len(testdata)
	for _, testlogo := range testdata {
		testcase := testLogoToTestVisitor(testlogo)

		if err := testcase.CheckTestCase(); err != nil {
			t.Errorf("FAIL\n%s\nXML:\n %s\n", err, testcase.XML)
			nbErrors++
		}
	}

	t.Logf("PASS RATIO = %v/%v\n", len-nbErrors, len)
}
Esempio n. 13
0
func (g *Generator) ProcessStartElement(el xmlutils.StartElement) (xmlutils.Visitor, xmlutils.ParserError) {
	if g.depth.IsRoot() {
		g.reset()
		for _, attr := range el.Attr {
			switch attr.Name.Space {
			case xmlutils.XML_NS:
				g.ProcessAttr(attr)

			case "":
				switch attr.Name.Local {
				case "uri":
					g.Uri.Value = attr.Value
					g.Uri.IncOccurence()

				case "version":
					g.Version.Value = attr.Value
					g.Version.IncOccurence()
				}
			default:
				g.Extension.ProcessAttr(attr, g)
			}
		}
	}

	if g.depth.Down() == xmlutils.MaxDepthReached {
		return g, xmlutils.NewError(LeafElementHasChild, "'generator' shoud not have childs")

	}

	return g, nil
}
Esempio n. 14
0
func TestSourceBasic(t *testing.T) {

	var testdata = []testSource{
		{`<source>Tomalak's Realm</source>`,
			xmlutils.NewError(MissingAttribute, ""),
			NewTestSource("", "Tomalak's Realm"),
		},
		{`<source url="http://www.tomaltak.org/links2.xml">Tomalak's Realm</source>`,
			nil,
			NewTestSource("http://www.tomaltak.org/links2.xml", "Tomalak's Realm"),
		},
	}

	nbErrors := 0
	len := len(testdata)
	for _, testsource := range testdata {
		testcase := _TestSourceToTestVisitor(testsource)

		if err := testcase.CheckTestCase(); err != nil {
			t.Errorf("FAIL\n%s\nXML:\n %s\n", err, testcase.XML)
			nbErrors++
		}
	}

	t.Logf("PASS RATIO = %v/%v\n", len-nbErrors, len)
}
Esempio n. 15
0
File: link.go Progetto: apognu/xml
func (c *Count) Validate() xmlutils.ParserError {
	errAgg := utils.NewErrorAggregator()
	link, ok := c.Parent.(*atom.Link)
	if !ok {
		errAgg.NewError(xmlutils.NewError(NotInLinkElement, "count attr should be placed in link element"))

	} else {
		if link.Rel.String() != "replies" {
			errAgg.NewError(xmlutils.NewError(LinkNotReplies, "link element should avec a 'replies' rel for this extension"))
		}
	}
	if err := c.Validator(c.Name().Local, c.Content); err != nil {
		errAgg.NewError(err)
	}

	return errAgg.ErrorObject()
}
Esempio n. 16
0
func (i *InlineXHTMLContent) flush() xmlutils.ParserError {
	err := i.Encoder.Flush()

	if err != nil {
		return xmlutils.NewError(CannotFlush, "cannot flush XHTML")
	}
	return nil
}
Esempio n. 17
0
func (i *InlineXHTMLContent) ProcessCharData(el xml.CharData) (xmlutils.Visitor, xmlutils.ParserError) {
	if len(strings.Fields(string(el))) > 0 {
		if err := i.flush(); err != nil {
			return i, err
		}

		if _, err := i.Content.Write(el); err != nil {
			return i, xmlutils.NewError(CannotFlush, "cannot flush content")
		}

		if i.depth.Level == 0 {
			return i, xmlutils.NewError(XHTMLRootNodeNotDiv, "XHTML element should have a root")
		}
	}

	return i, nil
}
Esempio n. 18
0
func TestDateBasic(t *testing.T) {

	var testdata = []testDate{
		{`<updated xml:lang="en-us" xml:base="http://yo.com">2003-12-13T18:30:02Z</updated>`,
			nil,
			DateWithBaseLang(NewTestDate("2003-12-13T18:30:02Z"), "en-us", "http://yo.com"),
		},
		{`<updated>2003-12-13T18:30:02Z</updated>`,
			nil,
			NewTestDate("2003-12-13T18:30:02Z"),
		},
		{`<updated>2003-12-13T18:30:02.25Z</updated>`,
			nil,
			NewTestDate("2003-12-13T18:30:02.25Z"),
		},
		{`<updated>2003-12-13T18:30:02+01:00</updated>`,
			nil,
			NewTestDate("2003-12-13T18:30:02+01:00"),
		},
		{`<updated>2003-12-13T18:30:02.25+01:00</updated>`,
			nil,
			NewTestDate("2003-12-13T18:30:02.25+01:00"),
		},
		{`<updated>2003-12-13t18:30:02z</updated>`,
			xmlutils.NewError(DateFormat, ""),
			NewTestDate("0"),
		},
		{`<updated>2003-12-13T18:30:02.25</updated>`,
			xmlutils.NewError(DateFormat, ""),
			NewTestDate("0"),
		},
	}
	nbErrors := 0
	len := len(testdata)
	for _, testdate := range testdata {
		testcase := testDateToTestVisitor(testdate)

		if err := testcase.CheckTestCase(); err != nil {
			t.Errorf("FAIL\n%s\nXML:\n %s\n", err, testcase.XML)
			nbErrors++
		}
	}

	t.Logf("PASS RATIO = %v/%v\n", len-nbErrors, len)
}
Esempio n. 19
0
func (d *Date) ProcessCharData(el xml.CharData) (xmlutils.Visitor, xmlutils.ParserError) {
	var err error
	d.Time, err = time.Parse(time.RFC3339, string(el))

	if err != nil || d.Time.IsZero() {
		return d, xmlutils.NewError(DateFormat, fmt.Sprintf("date not well formatted '%v'", string(el)))
	}
	return d, nil
}
Esempio n. 20
0
func TestCloudBasic(t *testing.T) {

	var testdata = []testCloud{
		{`<cloud domain="rpc.sys.com" port="80" path="/RPC2" registerProcedure="myCloud.rssPleaseNotify" protocol="xml-rpc" />`,
			nil,
			NewTestCloud("rpc.sys.com", "80", "/RPC2", "myCloud.rssPleaseNotify", "xml-rpc"),
		},
		{`<cloud port="80" path="/RPC2" registerProcedure="myCloud.rssPleaseNotify" protocol="xml-rpc" />`,
			xmlutils.NewError(MissingAttribute, ""),
			NewTestCloud("", "80", "/RPC2", "myCloud.rssPleaseNotify", "xml-rpc"),
		},
		{`<cloud domain="rpc.sys.com" path="/RPC2" registerProcedure="myCloud.rssPleaseNotify" protocol="xml-rpc" />`,
			xmlutils.NewError(MissingAttribute, ""),
			NewTestCloud("rpc.sys.com", "", "/RPC2", "myCloud.rssPleaseNotify", "xml-rpc"),
		},
		{`<cloud domain="rpc.sys.com" port="80" registerProcedure="myCloud.rssPleaseNotify" protocol="xml-rpc" />`,
			xmlutils.NewError(MissingAttribute, ""),
			NewTestCloud("rpc.sys.com", "80", "", "myCloud.rssPleaseNotify", "xml-rpc"),
		},
		{`<cloud domain="rpc.sys.com" port="80" path="/RPC2" protocol="xml-rpc" />`,
			xmlutils.NewError(MissingAttribute, ""),
			NewTestCloud("rpc.sys.com", "80", "/RPC2", "", "xml-rpc"),
		},
		{`<cloud domain="rpc.sys.com" port="80" path="/RPC2" registerProcedure="myCloud.rssPleaseNotify" />`,
			xmlutils.NewError(MissingAttribute, ""),
			NewTestCloud("rpc.sys.com", "80", "/RPC2", "myCloud.rssPleaseNotify", ""),
		},
	}

	nbErrors := 0
	len := len(testdata)
	for _, testcloud := range testdata {
		testcase := _TestCloudToTestVisitor(testcloud)

		if err := testcase.CheckTestCase(); err != nil {
			t.Errorf("FAIL\n%s\nXML:\n %s\n", err, testcase.XML)
			nbErrors++
		}
	}

	t.Logf("PASS RATIO = %v/%v\n", len-nbErrors, len)
}
Esempio n. 21
0
func (i *InlineXHTMLContent) ProcessStartElement(el xmlutils.StartElement) (xmlutils.Visitor, xmlutils.ParserError) {
	err := utils.NewErrorAggregator()
	if i.depth.Level == 0 && el.Name.Local != "div" {
		err.NewError(xmlutils.NewError(XHTMLRootNodeNotDiv, "Inline XHTML root node must be a div"))
	}

	if i.completed == true {
		err.NewError(xmlutils.NewError(NotUniqueChild, "Inline XHTML should be contained in a unique node"))
	}

	i.depth.Down()
	if error := i.CheckXHTMLSpace(el); error != nil {
		err.NewError(error)
	}
	if error := i.EncodeXHTMLToken(el); error != nil {
		err.NewError(xmlutils.NewError(XHTMLEncodeToStringError, "cannot encode XHTML"))
	}

	return i, err.ErrorObject()
}
Esempio n. 22
0
func (b *BasicElement) Validate() xmlutils.ParserError {
	error := utils.NewErrorAggregator()

	b.Extension.Validate(&error)

	if err := b.Content.Validate(); err != nil {
		error.NewError(xmlutils.NewError(err.Flag(), fmt.Sprintf("%s's %s", b.name.Local, err.Msg())))
	}

	return error.ErrorObject()
}
Esempio n. 23
0
func (i *InlineOtherContent) validate() xmlutils.ParserError {
	error := utils.NewErrorAggregator()

	xmlutils.ValidateElements("inlineothercontent", &error, i.Type)

	if strings.HasPrefix(i.Type.Value, "text/") && i.hasChild {
		error.NewError(xmlutils.NewError(LeafElementHasChild, "text content should not have child"))
	}

	return error.ErrorObject()
}
Esempio n. 24
0
File: item.go Progetto: apognu/xml
func (i *Item) validate() xmlutils.ParserError {
	err := utils.NewErrorAggregator()

	xmlutils.ValidateOccurenceCollection("item", &err, i.Occurences)
	i.Extension.Validate(&err)

	if i.Occurences.Count("description") == 0 && i.Occurences.Count("title") == 0 {
		err.NewError(xmlutils.NewError(MissingAttribute, "item should have at least a title or a description"))
	}

	return err.ErrorObject()
}
Esempio n. 25
0
func (u *UnescapedContent) ProcessCharData(el xml.CharData) (xmlutils.Visitor, xmlutils.ParserError) {
	if len(strings.Fields(string(el))) > 0 {
		if ferr := u.flush(); ferr != nil {
			return u, ferr
		}

		if _, err := u.Content.Write(el); err != nil {
			return u, xmlutils.NewError(CannotFlush, "cannot flush content")
		}
	}

	return u, nil
}
Esempio n. 26
0
File: date.go Progetto: apognu/xml
func (d *Date) ProcessStartElement(el xmlutils.StartElement) (xmlutils.Visitor, xmlutils.ParserError) {
	if d.depth.IsRoot() {
		for _, attr := range el.Attr {
			d.Extension.ProcessAttr(attr, d)
		}
	}

	if d.depth.Down() == xmlutils.RootLevel {
		return d.Parent, xmlutils.NewError(LeafElementHasChild, "date construct shoud not have childs")
	}

	return d, nil
}
Esempio n. 27
0
File: date.go Progetto: apognu/xml
func (d *Date) ProcessCharData(el xml.CharData) (xmlutils.Visitor, xmlutils.ParserError) {
	var err error

	d.RawContent = string(el)
	for _, dateFormat := range rssDateFormat {
		d.Time, err = time.Parse(dateFormat, string(el))
		if err == nil && !d.Time.IsZero() {
			return d, nil
		}
	}

	return d, xmlutils.NewError(DateFormat, fmt.Sprintf("date not well formatted '%v'", string(el)))
}
Esempio n. 28
0
func TestCategoryBasic(t *testing.T) {

	var testdata = []testCategory{
		{`<category xml:lang="en-us" xml:base="http://yo.com" scheme='https://www.yo.com' term='music' />`,
			nil,
			CategoryWithBaseLang(NewTestCategory("https://www.yo.com", "music", ""), "en-us", "http://yo.com"),
		},

		{`<category scheme='https://www.yo.com' term='music' />`,
			nil,
			NewTestCategory("https://www.yo.com", "music", ""),
		},
		{`<category scheme='https://www.tbray.org/ongoing/What/' />`,
			xmlutils.NewError(MissingAttribute, ""),
			NewTestCategory("https://www.tbray.org/ongoing/What/", "", ""),
		},
		{`<category term="music" label='house' />`,
			nil,
			NewTestCategory("", "music", "house"),
		},
		{`<category term="music" label='house' scheme='http://www.%scheme.com'/>`,
			xmlutils.NewError(IriNotValid, ""),
			NewTestCategory("http://www.%scheme.com", "music", "house"),
		},
	}
	nbErrors := 0
	len := len(testdata)
	for _, testcategory := range testdata {
		testcase := testCategoryToTestVisitor(testcategory)

		if err := testcase.CheckTestCase(); err != nil {
			t.Errorf("FAIL\n%s\nXML:\n %s\n", err, testcase.XML)
			nbErrors++
		}
	}

	t.Logf("PASS RATIO = %v/%v\n", len-nbErrors, len)
}
Esempio n. 29
0
func (i *InlineOtherContent) ProcessEndElement(el xml.EndElement) (xmlutils.Visitor, xmlutils.ParserError) {
	level := i.depth.Up()

	if level == xmlutils.RootLevel {
		i.Encoder.Flush()
		return i.Parent, i.validate()
	}

	if err := i.Encoder.EncodeToken(el); err != nil {
		return i, xmlutils.NewError(XHTMLEncodeToStringError, "cannot encode XHTML")
	}

	return i, nil
}
Esempio n. 30
0
func TestLinkBasic(t *testing.T) {

	var testdata = []testLink{
		{`<link xml:lang="en-us" xml:base="http://yo.com" href="http://www.go.com" rel="alternate" type="text/html"/>`,
			nil,
			LinkWithBaseLang(NewTestLink("http://www.go.com", "alternate", "text/html", "", "", ""), "en-us", "http://yo.com"),
		},
		{`<link rel="alternate" type="text/html"/>`,
			xmlutils.NewError(MissingAttribute, ""),
			NewTestLink("", "alternate", "text/html", "", "", ""),
		},
		{`<link rel="alternate" type="text/html" href="http://%%%www.go.com"/>`,
			xmlutils.NewError(IriNotValid, ""),
			NewTestLink("http://%%%www.go.com", "alternate", "text/html", "", "", ""),
		},
		{`<link rel="alternate" type="text/html" href="http://www.go.com" length="-56"/>`,
			xmlutils.NewError(NotPositiveNumber, ""),
			NewTestLink("http://www.go.com", "alternate", "text/html", "", "", "-56"),
		},
		{`<link rel="alternate" type="text/html" href="http://www.go.com" length="ab"/>`,
			xmlutils.NewError(NotPositiveNumber, ""),
			NewTestLink("http://www.go.com", "alternate", "text/html", "", "", "ab"),
		},
	}
	nbErrors := 0
	len := len(testdata)
	for _, testlink := range testdata {
		testcase := testLinkToTestVisitor(testlink)

		if err := testcase.CheckTestCase(); err != nil {
			t.Errorf("FAIL\n%s\nXML:\n %s\n", err, testcase.XML)
			nbErrors++
		}
	}

	t.Logf("PASS RATIO = %v/%v\n", len-nbErrors, len)
}