Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: check graph message names #157

Merged
merged 3 commits into from
Oct 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
//
// Copyright © 2024 Agora
// This file is part of TEN Framework, an open source project.
// Licensed under the Apache License, Version 2.0, with certain conditions.
// Refer to the "LICENSE" file in the root directory for more information.
//
use std::collections::HashMap;

use anyhow::{Ok, Result};

use crate::pkg_info::graph::Graph;

impl Graph {
// The following connection is invalid.
//
// "connections": [
// {
// "extension": "some_ext",
// "extension_group": "some_group",
// "cmd": [
// {
// "name": "some_cmd",
// "dest": [
// {
// "extension": "ext_2",
// "extension_group": "group_2"
// }
// ]
// }
// ]
// },
// {
// "extension": "some_ext",
// "extension_group": "some_group",
// "cmd": [
// {
// "name": "another_cmd",
// "dest": [
// {
// "extension": "ext_3",
// "extension_group": "group_3"
// }
// ]
// }
// ]
// }
// ]
pub fn check_extension_uniqueness_in_connections(&self) -> Result<()> {
let mut errors: Vec<String> = vec![];
let mut extensions: HashMap<String, usize> = HashMap::new();

for (conn_idx, connection) in
self.connections.as_ref().unwrap().iter().enumerate()
{
let extension = format!(
"{}:{}:{}",
connection.get_app_uri(),
connection.extension_group,
connection.extension
);

if let Some(idx) = extensions.get(&extension) {
errors.push(format!(
"extension '{}' is defined in connection[{}] and connection[{}], merge them into one section.",
connection.extension, idx, conn_idx
));
} else {
extensions.insert(extension, conn_idx);
}
}

if errors.is_empty() {
Ok(())
} else {
Err(anyhow::anyhow!("{}", errors.join("\n")))
}
}
}
135 changes: 135 additions & 0 deletions core/src/ten_rust/src/pkg_info/graph/check/message_names.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
//
// Copyright © 2024 Agora
// This file is part of TEN Framework, an open source project.
// Licensed under the Apache License, Version 2.0, with certain conditions.
// Refer to the "LICENSE" file in the root directory for more information.
//
use std::collections::HashMap;

use anyhow::{Ok, Result};

use crate::pkg_info::graph::{Graph, GraphConnection, GraphMessageFlow};

impl Graph {
fn check_if_message_names_are_duplicated(&self) -> Result<()> {
let mut errors: Vec<String> = vec![];
for (conn_idx, connection) in
self.connections.as_ref().unwrap().iter().enumerate()
{
if let Some(errs) =
self.check_if_message_name_duplicated_in_connection(connection)
{
errors.push(format!("- connection[{}]:", conn_idx));
for err in errs {
errors.push(format!(" {}", err));
}
}
}

if errors.is_empty() {
Ok(())
} else {
Err(anyhow::anyhow!("{}", errors.join("\n")))
}
}

fn check_if_message_name_duplicated_group_by_msg_type(
&self,
flows: &[GraphMessageFlow],
) -> Vec<String> {
let mut errors: Vec<String> = vec![];

let mut msg_names: HashMap<String, usize> = HashMap::new();
for (flow_idx, flow) in flows.iter().enumerate() {
if let Some(idx) = msg_names.get(&flow.name) {
errors.push(format!(
"'{}' is defined in flow[{}] and flow[{}].",
flow.name, idx, flow_idx
));
} else {
msg_names.insert(flow.name.clone(), flow_idx);
}
}

errors
}

fn check_if_message_name_duplicated_in_connection(
&self,
connection: &GraphConnection,
) -> Option<Vec<String>> {
let mut errors: Vec<String> = vec![];

if let Some(cmd) = &connection.cmd {
let errs =
self.check_if_message_name_duplicated_group_by_msg_type(cmd);
if !errs.is_empty() {
errors.push(
"- Merge the following cmd into one section:".to_string(),
);
for err in errs {
errors.push(format!(" {}", err));
}
}
}

if let Some(data) = &connection.data {
let errs =
self.check_if_message_name_duplicated_group_by_msg_type(data);
if !errs.is_empty() {
errors.push(
"- Merge the following data into one section:".to_string(),
);
for err in errs {
errors.push(format!(" {}", err));
}
}
}

if let Some(audio_frame) = &connection.audio_frame {
let errs = self.check_if_message_name_duplicated_group_by_msg_type(
audio_frame,
);
if !errs.is_empty() {
errors.push(
"- Merge the following auto_frame into one section:"
.to_string(),
);
for err in errs {
errors.push(format!(" {}", err));
}
}
}

if let Some(video_frame) = &connection.video_frame {
let errs = self.check_if_message_name_duplicated_group_by_msg_type(
video_frame,
);
if !errs.is_empty() {
errors.push(
"- Merge the following video_frame into one section:"
.to_string(),
);
for err in errs {
errors.push(format!(" {}", err));
}
}
}

if errors.is_empty() {
None
} else {
Some(errors)
}
}

pub fn check_message_names(&self) -> Result<()> {
if self.connections.is_none() {
return Ok(());
}

self.check_if_message_names_are_duplicated()?;

Ok(())
}
}
2 changes: 2 additions & 0 deletions core/src/ten_rust/src/pkg_info/graph/check/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,6 @@
pub mod connections_are_compatible;
pub mod connections_nodes_are_defined;
pub mod duplicated_nodes;
pub mod extension_uniqueness_in_connections;
pub mod message_names;
pub mod nodes_are_installed;
45 changes: 45 additions & 0 deletions core/src/ten_rust/src/pkg_info/graph/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,8 @@ impl Graph {
self.check_if_extensions_used_in_connections_have_defined_in_nodes()?;
self.check_if_nodes_have_installed(existed_pkgs_of_all_apps)?;
self.check_connections_compatible(existed_pkgs_of_all_apps)?;
self.check_extension_uniqueness_in_connections()?;
self.check_message_names()?;

Ok(())
}
Expand Down Expand Up @@ -459,4 +461,47 @@ mod tests {
"'app' should not be declared, as not any node has declared it"
));
}

#[test]
fn test_graph_same_extension_in_two_section_of_connections() {
let graph_str = include_str!(
"test_data_embed/graph_same_extension_in_two_section_of_connections.json"
);

let graph = Graph::from_str(graph_str).unwrap();

let result = graph.check_extension_uniqueness_in_connections();

assert!(result.is_err());
println!("Error: {:?}", result);

let msg = result.err().unwrap().to_string();
assert!(msg.contains("extension 'some_extension' is defined in connection[0] and connection[1]"));
}

#[test]
fn test_graph_duplicated_cmd_name_in_one_connection() {
let graph_str = include_str!(
"test_data_embed/graph_duplicated_cmd_name_in_one_connection.json"
);

let graph = Graph::from_str(graph_str).unwrap();
let result = graph.check_message_names();
assert!(result.is_err());
println!("Error: {:?}", result);

let msg = result.err().unwrap().to_string();
assert!(msg.contains("'hello' is defined in flow[0] and flow[1]"));
}

#[test]
fn test_graph_messages_same_name_in_different_type_are_ok() {
let graph_str = include_str!(
"test_data_embed/graph_messages_same_name_in_different_type_are_ok.json"
);

let graph = Graph::from_str(graph_str).unwrap();
let result = graph.check_message_names();
assert!(result.is_ok());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
{
"nodes": [
{
"type": "extension",
"name": "some_extension",
"addon": "default_extension_go",
"extension_group": "some_group"
},
{
"type": "extension",
"name": "another_ext",
"addon": "default_extension_go",
"extension_group": "some_group"
},
{
"type": "extension",
"name": "third_ext",
"addon": "default_extension_go",
"extension_group": "some_group"
}
],
"connections": [
{
"extension": "some_extension",
"extension_group": "some_group",
"cmd": [
{
"name": "hello",
"dest": [
{
"extension_group": "some_group",
"extension": "another_ext"
}
]
},
{
"name": "hello",
"dest": [
{
"extension_group": "some_group",
"extension": "third_ext"
}
]
}
]
},
{
"extension": "another_ext",
"extension_group": "some_group",
"data": [
{
"name": "hello",
"dest": [
{
"extension_group": "some_group",
"extension": "third_ext"
},
{
"extension_group": "some_group",
"extension": "some_extension"
}
]
}
]
}
]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
{
"nodes": [
{
"type": "extension",
"name": "some_extension",
"addon": "default_extension_go",
"extension_group": "some_group"
},
{
"type": "extension",
"name": "another_ext",
"addon": "default_extension_go",
"extension_group": "some_group"
},
{
"type": "extension",
"name": "third_ext",
"addon": "default_extension_go",
"extension_group": "some_group"
}
],
"connections": [
{
"extension": "some_extension",
"extension_group": "some_group",
"cmd": [
{
"name": "hello",
"dest": [
{
"extension_group": "some_group",
"extension": "another_ext"
}
]
}
],
"data": [
{
"name": "hello",
"dest": [
{
"extension_group": "some_group",
"extension": "third_ext"
}
]
}
]
}
]
}
Loading
Loading