// Copyright 2008-2012 severally by the contributors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package net.sf.practicalxml.converter;

import java.util.concurrent.atomic.AtomicReference;

import org.w3c.dom.Element;

import junit.framework.TestCase;

import net.sf.practicalxml.DomUtil;

public class TestConversionException
extends TestCase
{
    public void testFieldConstructor() throws Exception
    {
        ConversionException ex = new ConversionException("foo", "bar");
        assertEquals("message", "foo: bar", ex.getMessage());
        assertEquals("field",   "bar", ex.getField());
    }


    public void testRethrowConstructor() throws Exception
    {
        Exception cause = new IllegalArgumentException();
        ConversionException ex0 = new ConversionException("foo", cause);

        ConversionException ex1 = new ConversionException(ex0, "bar");
        assertEquals("message", "foo: bar", ex1.getMessage());
        assertEquals("field",   "bar", ex1.getField());
        assertSame("cause",     cause, ex1.getCause());

        ConversionException ex2 = new ConversionException(ex1, "baz");
        assertEquals("message", "foo: baz.bar", ex2.getMessage());
        assertEquals("field",   "baz.bar", ex2.getField());
        assertSame("cause",     cause, ex2.getCause());
    }


    public void testRethrowConstructorPreservesOriginalStacktrace() throws Exception
    {
        // this is ugly, but it gets the job done
        final Exception cause = new IllegalArgumentException();
        final AtomicReference<StackTraceElement[]> origTrace = new AtomicReference<StackTraceElement[]>();
        try
        {
            new Runnable()
            {
                public void run()
                {
                    try
                    {
                        foo();
                    }
                    catch (ConversionException ex)
                    {
                        origTrace.set(ex.getStackTrace());
                        throw ex;
                    }
                }

                private void foo()
                {
                    throw new ConversionException("foo", "bar", cause);
                }
            }.run();
        }
        catch (ConversionException ex0)
        {
            ConversionException ex = new ConversionException(ex0, "baz");
            assertEquals("message",   "foo: baz.bar", ex.getMessage());
            assertEquals("field",     "baz.bar", ex.getField());
            assertSame("cause",        cause, ex.getCause());
            assertEquals("trace size", origTrace.get().length, ex.getStackTrace().length);
            assertEquals("trace root", origTrace.get()[0], ex.getStackTrace()[0]);
        }
    }


    public void testXPathException() throws Exception
    {
        Element root = DomUtil.newDocument("foo");
        Element child = DomUtil.appendChild(root, "bar");
        Element gc = DomUtil.appendChild(child, "baz");

        ConversionException ex = new ConversionException("test", gc);
        assertEquals("message", "test: /foo/bar/baz", ex.getMessage());
        assertEquals("xpath",   "/foo/bar/baz", ex.getXPath());
    }

}
