// 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.

package xml

import (
	"io";
	"os";
	"reflect";
	"strings";
	"testing";
)

const testInput = `
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<body xmlns:foo="ns1" xmlns="ns2" xmlns:tag="ns3" `
	"\r\n\t" `  >
  <hello lang="en">World &lt;&gt;&apos;&quot; &#x767d;&#40300;翔</hello>
  <goodbye />
  <outer foo:attr="value" xmlns:tag="ns4">
    <inner/>
  </outer>
  <tag:name>
    Some text here.
  </tag:name>
</body><!-- missing final newline -->`

var rawTokens = []Token{
	CharData(strings.Bytes("\n")),
	ProcInst{"xml", strings.Bytes(`version="1.0" encoding="UTF-8"`)},
	CharData(strings.Bytes("\n")),
	Directive(strings.Bytes(`DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"`)),
	CharData(strings.Bytes("\n")),
	StartElement{Name{"", "body"}, []Attr{Attr{Name{"xmlns", "foo"}, "ns1"}, Attr{Name{"", "xmlns"}, "ns2"}, Attr{Name{"xmlns", "tag"}, "ns3"}}},
	CharData(strings.Bytes("\n  ")),
	StartElement{Name{"", "hello"}, []Attr{Attr{Name{"", "lang"}, "en"}}},
	CharData(strings.Bytes("World <>'\" 白鵬翔")),
	EndElement{Name{"", "hello"}},
	CharData(strings.Bytes("\n  ")),
	StartElement{Name{"", "goodbye"}, nil},
	EndElement{Name{"", "goodbye"}},
	CharData(strings.Bytes("\n  ")),
	StartElement{Name{"", "outer"}, []Attr{Attr{Name{"foo", "attr"}, "value"}, Attr{Name{"xmlns", "tag"}, "ns4"}}},
	CharData(strings.Bytes("\n    ")),
	StartElement{Name{"", "inner"}, nil},
	EndElement{Name{"", "inner"}},
	CharData(strings.Bytes("\n  ")),
	EndElement{Name{"", "outer"}},
	CharData(strings.Bytes("\n  ")),
	StartElement{Name{"tag", "name"}, nil},
	CharData(strings.Bytes("\n    Some text here.\n  ")),
	EndElement{Name{"tag", "name"}},
	CharData(strings.Bytes("\n")),
	EndElement{Name{"", "body"}},
	Comment(strings.Bytes(" missing final newline ")),
}

var cookedTokens = []Token{
	CharData(strings.Bytes("\n")),
	ProcInst{"xml", strings.Bytes(`version="1.0" encoding="UTF-8"`)},
	CharData(strings.Bytes("\n")),
	Directive(strings.Bytes(`DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"`)),
	CharData(strings.Bytes("\n")),
	StartElement{Name{"ns2", "body"}, []Attr{Attr{Name{"xmlns", "foo"}, "ns1"}, Attr{Name{"", "xmlns"}, "ns2"}, Attr{Name{"xmlns", "tag"}, "ns3"}}},
	CharData(strings.Bytes("\n  ")),
	StartElement{Name{"ns2", "hello"}, []Attr{Attr{Name{"", "lang"}, "en"}}},
	CharData(strings.Bytes("World <>'\" 白鵬翔")),
	EndElement{Name{"ns2", "hello"}},
	CharData(strings.Bytes("\n  ")),
	StartElement{Name{"ns2", "goodbye"}, nil},
	EndElement{Name{"ns2", "goodbye"}},
	CharData(strings.Bytes("\n  ")),
	StartElement{Name{"ns2", "outer"}, []Attr{Attr{Name{"ns1", "attr"}, "value"}, Attr{Name{"xmlns", "tag"}, "ns4"}}},
	CharData(strings.Bytes("\n    ")),
	StartElement{Name{"ns2", "inner"}, nil},
	EndElement{Name{"ns2", "inner"}},
	CharData(strings.Bytes("\n  ")),
	EndElement{Name{"ns2", "outer"}},
	CharData(strings.Bytes("\n  ")),
	StartElement{Name{"ns3", "name"}, nil},
	CharData(strings.Bytes("\n    Some text here.\n  ")),
	EndElement{Name{"ns3", "name"}},
	CharData(strings.Bytes("\n")),
	EndElement{Name{"ns2", "body"}},
	Comment(strings.Bytes(" missing final newline ")),
}

type stringReader struct {
	s	string;
	off	int;
}

func (r *stringReader) Read(b []byte) (n int, err os.Error) {
	if r.off >= len(r.s) {
		return 0, os.EOF
	}
	for r.off < len(r.s) && n < len(b) {
		b[n] = r.s[r.off];
		n++;
		r.off++;
	}
	return;
}

func (r *stringReader) ReadByte() (b byte, err os.Error) {
	if r.off >= len(r.s) {
		return 0, os.EOF
	}
	b = r.s[r.off];
	r.off++;
	return;
}

func StringReader(s string) io.Reader	{ return &stringReader{s, 0} }

func TestRawToken(t *testing.T) {
	p := NewParser(StringReader(testInput));

	for i, want := range rawTokens {
		have, err := p.RawToken();
		if err != nil {
			t.Fatalf("token %d: unexpected error: %s", i, err)
		}
		if !reflect.DeepEqual(have, want) {
			t.Errorf("token %d = %#v want %#v", i, have, want)
		}
	}
}

func TestToken(t *testing.T) {
	p := NewParser(StringReader(testInput));

	for i, want := range cookedTokens {
		have, err := p.Token();
		if err != nil {
			t.Fatalf("token %d: unexpected error: %s", i, err)
		}
		if !reflect.DeepEqual(have, want) {
			t.Errorf("token %d = %#v want %#v", i, have, want)
		}
	}
}
