use crate::tests::utils;
use crate::token::GraphQLTokenKind;
use crate::GraphQLTokenStream;
#[test]
fn consume_returns_owned_token_with_correct_fields() {
let tokens = vec![
utils::mock_name_token("type"),
utils::mock_eof_token(),
];
let mut stream = GraphQLTokenStream::new(
utils::MockTokenSource::new(tokens),
);
let token = stream.consume().expect("should return a token");
assert!(
matches!(token.kind, GraphQLTokenKind::Name(ref n) if n == "type"),
);
assert_eq!(token.span.start, 0);
assert_eq!(token.span.end, 0);
assert!(token.preceding_trivia.is_empty());
}
#[test]
fn consumed_token_is_independent_of_stream() {
let tokens = vec![
utils::mock_name_token("first"),
utils::mock_name_token("second"),
utils::mock_eof_token(),
];
let mut stream = GraphQLTokenStream::new(
utils::MockTokenSource::new(tokens),
);
let mut consumed = stream.consume().unwrap();
consumed.kind = GraphQLTokenKind::Eof;
let next = stream.peek().unwrap();
assert!(
matches!(next.kind, GraphQLTokenKind::Name(ref n) if n == "second"),
"mutating consumed token should not affect stream",
);
}
#[test]
fn peek_then_drop_then_consume_pattern() {
let tokens = vec![
utils::mock_name_token("type"),
utils::mock_name_token("Query"),
utils::mock_eof_token(),
];
let mut stream = GraphQLTokenStream::new(
utils::MockTokenSource::new(tokens),
);
let is_name = matches!(
stream.peek().map(|t| &t.kind),
Some(GraphQLTokenKind::Name(_)),
);
assert!(is_name);
let owned = stream.consume().unwrap();
assert!(
matches!(owned.kind, GraphQLTokenKind::Name(ref n) if n == "type"),
);
let next = stream.peek().unwrap();
assert!(
matches!(next.kind, GraphQLTokenKind::Name(ref n) if n == "Query"),
);
}
#[test]
fn consume_all_tokens_into_vec() {
let expected_names = [
"type", "Query", "field", "String",
];
let tokens: Vec<_> = expected_names
.iter()
.map(|n| utils::mock_name_token(n))
.chain(std::iter::once(utils::mock_eof_token()))
.collect();
let mut stream = GraphQLTokenStream::new(
utils::MockTokenSource::new(tokens),
);
let mut collected = Vec::new();
while let Some(token) = stream.consume() {
collected.push(token);
}
assert_eq!(collected.len(), 5);
for (i, name) in expected_names.iter().enumerate() {
assert!(
matches!(
collected[i].kind,
GraphQLTokenKind::Name(ref n) if n == name
),
"token {i} should be Name({name})",
);
}
assert!(matches!(collected[4].kind, GraphQLTokenKind::Eof));
assert!(stream.consume().is_none());
assert_eq!(stream.current_buffer_len(), 0);
}
#[test]
fn vecdeque_buffer_bounded_during_lookahead_cycles() {
let total_tokens = 600;
let lookahead = 5;
let tokens: Vec<_> = (0..total_tokens)
.map(|i| utils::mock_name_token(&format!("t{i}")))
.chain(std::iter::once(utils::mock_eof_token()))
.collect();
let mut stream = GraphQLTokenStream::new(
utils::MockTokenSource::new(tokens),
);
let mut consumed_count = 0usize;
loop {
let peeked_count = (0..lookahead)
.filter(|&n| stream.peek_nth(n).is_some())
.count();
if peeked_count == 0 {
break;
}
assert!(
stream.current_buffer_len() <= lookahead,
"buffer len {} exceeds lookahead {} at token {}",
stream.current_buffer_len(),
lookahead,
consumed_count,
);
let token = stream.consume().unwrap();
let expected = format!("t{consumed_count}");
if consumed_count < total_tokens {
assert!(
matches!(
token.kind,
GraphQLTokenKind::Name(ref n) if n == &expected
),
"expected {expected} at position {consumed_count}",
);
}
consumed_count += 1;
}
assert_eq!(consumed_count, total_tokens + 1); }