trivet 3.1.0

The trivet Parser Library
Documentation
// Trivet
// Copyright (c) 2025 by Stacy Prowell.  All rights reserved.
// https://gitlab.com/binary-tools/trivet

//! Tests of the errors module.

use crate::errors;
use crate::errors::ParseError;
use crate::loc::Loc;
use std::error::Error as StdError;
use std::io::Error;
use std::io::ErrorKind;

#[test]
fn error() {
    // Simple error strings.
    let internal = Loc::Internal;
    let console = Loc::Console {
        line: 17,
        column: 21,
    };
    let file = Loc::File {
        name: "tom".to_string(),
        line: 17,
        column: 21,
    };
    let nfe = Error::from(ErrorKind::NotFound);
    let err = errors::error(internal, nfe);
    assert_eq!(err.to_string(), "(internal): entity not found");
    let nfe = Error::from(ErrorKind::NotFound);
    let err = errors::error(console, nfe);
    assert_eq!(err.to_string(), "17:21: entity not found");
    let nfe = Error::from(ErrorKind::NotFound);
    let err = errors::error(file, nfe);
    assert_eq!(err.to_string(), "tom:17:21: entity not found");

    // Nested error chain.
    let file = Loc::File {
        name: "tom".to_string(),
        line: 17,
        column: 21,
    };
    let nfe = Error::from(ErrorKind::NotFound);
    let err = errors::io_error(file, nfe);
    assert_eq!(err.to_string(), "tom:17:21: I/O Error: entity not found");

    // Checking cause.
    let internal = Loc::Internal;
    let nfe = Error::from(ErrorKind::NotFound);
    let err = errors::io_error(internal, nfe);
    let cause = err.source();
    assert_eq!(cause.unwrap().to_string(), "entity not found");
    let err = errors::unimplemented_error(Loc::Internal, "fire");
    assert!(err.source().is_none());
}

#[test]
fn types() {
    // Test all the error types except I/O error, tested above.
    let file = Loc::File {
        name: "tom".to_string(),
        line: 17,
        column: 21,
    };
    assert_eq!(
        errors::unexpected_eof_error(file.clone()).to_string(),
        "tom:17:21: I/O Error: Unexpected end of file"
    );
    assert_eq!(
        errors::syntax_error(file.clone(), "bad syntax").to_string(),
        "tom:17:21: Syntax Error: bad syntax"
    );
    assert_eq!(
        errors::unexpected_text_error(file.clone(), "a thing", "a different thing").to_string(),
        "tom:17:21: Expected a thing, but found a different thing"
    );
    assert_eq!(
        errors::unexpected_character_error(file.clone(), "ampersand", '&').to_string(),
        "tom:17:21: Expected ampersand, but found '&'"
    );
    assert_eq!(
        errors::internal_error(file.clone(), "hrung collapsed").to_string(),
        "tom:17:21: Internal Error: hrung collapsed"
    );
    assert_eq!(
        errors::not_found_error(file.clone(), "keys").to_string(),
        "tom:17:21: Could not find keys"
    );
    assert_eq!(
        errors::unimplemented_error(file.clone(), "cold fusion").to_string(),
        "tom:17:21: Not Implemented: cold fusion"
    );

    #[allow(invalid_from_utf8)]
    match std::str::from_utf8(b"\xc3\x28") {
        Ok(_) => {}
        Err(err) => {
            let pe = errors::error(file.clone(), err);
            assert_eq!(pe.loc(), &file);
            if let ParseError::Error { loc: _, cause } = pe {
                assert_eq!(
                    cause.to_string(),
                    "invalid utf-8 sequence of 1 bytes from index 0"
                )
            }
        }
    }
    assert_eq!(errors::unexpected_eof_error(file.clone()).loc(), &file);
    assert_eq!(
        errors::syntax_error(file.clone(), "bad syntax").loc(),
        &file
    );
    assert_eq!(
        errors::unexpected_text_error(file.clone(), "a thing", "a different thing").loc(),
        &file
    );
    assert_eq!(
        errors::unexpected_character_error(file.clone(), "ampersand", '&').loc(),
        &file
    );
    assert_eq!(
        errors::internal_error(file.clone(), "hrung collapsed").loc(),
        &file
    );
    assert_eq!(errors::not_found_error(file.clone(), "keys").loc(), &file);
    assert_eq!(
        errors::unimplemented_error(file.clone(), "cold fusion").loc(),
        &file
    );
}