use std::mem::{align_of, size_of};
use zerocopy::FromBytes;
use crate::constant::{ColumnFlags, ColumnType};
use crate::protocol::command::{ColumnDefinition, ColumnDefinitionBytes, ColumnDefinitionTail};
use crate::test_macros::{check, check_eq, check_err};
#[test]
fn column_definition_tail_size() {
assert_eq!(size_of::<ColumnDefinitionTail>(), 12);
}
#[test]
fn column_definition_tail_has_alignment_of_1() {
assert_eq!(align_of::<ColumnDefinitionTail>(), 1);
}
#[test]
fn column_definition_tail_parsing() -> crate::error::Result<()> {
let data: [u8; 12] = [
0x21, 0x00, 0xFF, 0x00, 0x00, 0x00, 0xFD, 0x00, 0x00, 0x00, 0x00, 0x00, ];
let tail = ColumnDefinitionTail::ref_from_bytes(&data)?;
check_eq!(tail.charset(), 33);
check_eq!(tail.column_length(), 255);
let flags = tail.flags()?;
check!(flags.is_empty());
let col_type = tail.column_type()?;
check_eq!(col_type, ColumnType::MYSQL_TYPE_VAR_STRING);
Ok(())
}
#[test]
fn column_definition_tail_with_flags() -> crate::error::Result<()> {
let data: [u8; 12] = [
0x21, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x01, 0x21, 0x00, 0x00, 0x00, 0x00, ];
let tail = ColumnDefinitionTail::ref_from_bytes(&data)?;
let flags = tail.flags()?;
check!(flags.contains(ColumnFlags::NOT_NULL_FLAG));
check!(flags.contains(ColumnFlags::UNSIGNED_FLAG));
check!(!flags.contains(ColumnFlags::AUTO_INCREMENT_FLAG));
let col_type = tail.column_type()?;
check_eq!(col_type, ColumnType::MYSQL_TYPE_TINY);
Ok(())
}
#[test]
fn column_definition_tail_with_part_key_flag() -> crate::error::Result<()> {
let data: [u8; 12] = [
0x3f, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x03, 0x03, 0x42, 0x00, 0x00, 0x00, ];
let tail = ColumnDefinitionTail::ref_from_bytes(&data)?;
check_eq!(tail.charset(), 63);
check_eq!(tail.column_length(), 11);
let flags = tail.flags()?;
check!(flags.contains(ColumnFlags::NOT_NULL_FLAG));
check!(flags.contains(ColumnFlags::PRI_KEY_FLAG));
check!(flags.contains(ColumnFlags::AUTO_INCREMENT_FLAG));
check!(flags.contains(ColumnFlags::PART_KEY_FLAG));
let col_type = tail.column_type()?;
check_eq!(col_type, ColumnType::MYSQL_TYPE_LONG);
Ok(())
}
#[test]
fn column_definition_tail_invalid_column_type() -> crate::error::Result<()> {
let data: [u8; 12] = [
0x21, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, ];
let tail = ColumnDefinitionTail::ref_from_bytes(&data)?;
let result = tail.column_type();
let _err = check_err!(result);
Ok(())
}
#[test]
fn column_definition_bytes() -> crate::error::Result<()> {
let data: &[u8; 12] = &[
0x21, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x01, 0x21, 0x00, 0x00, 0x00, 0x00, ];
let col_bytes = ColumnDefinitionBytes(data);
let tail = col_bytes.tail()?;
check_eq!(tail.charset(), 33);
check_eq!(tail.column_length(), 255);
let flags = tail.flags()?;
check!(flags.contains(ColumnFlags::NOT_NULL_FLAG));
check!(flags.contains(ColumnFlags::UNSIGNED_FLAG));
let col_type = tail.column_type()?;
check_eq!(col_type, ColumnType::MYSQL_TYPE_TINY);
Ok(())
}
#[test]
fn column_definition_bytes_too_short() -> crate::error::Result<()> {
let data: &[u8; 8] = &[0; 8];
let col_bytes = ColumnDefinitionBytes(data);
let result = col_bytes.tail();
let _err = check_err!(result);
Ok(())
}
#[test]
fn column_definition_try_from() -> crate::error::Result<()> {
let mut packet = Vec::new();
packet.push(0x03);
packet.extend_from_slice(b"def");
packet.push(0x04);
packet.extend_from_slice(b"test");
packet.push(0x05);
packet.extend_from_slice(b"users");
packet.push(0x05);
packet.extend_from_slice(b"users");
packet.push(0x02);
packet.extend_from_slice(b"id");
packet.push(0x02);
packet.extend_from_slice(b"id");
packet.push(0x0c);
packet.extend_from_slice(&[
0x21, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, ]);
let col_bytes = ColumnDefinitionBytes(&packet);
let col_def = ColumnDefinition::try_from(col_bytes)?;
check_eq!(col_def.schema, b"test");
check_eq!(col_def.table_alias, b"users");
check_eq!(col_def.table_original, b"users");
check_eq!(col_def.name_alias, b"id");
check_eq!(col_def.name_original, b"id");
check_eq!(col_def.tail.charset(), 33);
check_eq!(col_def.tail.column_length(), 11);
let flags = col_def.tail.flags()?;
check!(flags.contains(ColumnFlags::NOT_NULL_FLAG));
check!(flags.contains(ColumnFlags::PRI_KEY_FLAG));
let col_type = col_def.tail.column_type()?;
check_eq!(col_type, ColumnType::MYSQL_TYPE_LONG);
Ok(())
}