batch_mode_batch_client/
upload_batch_file.rs

1// ---------------- [ File: batch-mode-batch-client/src/upload_batch_file.rs ]
2crate::ix!();
3
4#[async_trait]
5impl<E> UploadBatchFileCore for OpenAIClientHandle<E>
6where
7    E: Debug + Send + Sync + From<OpenAIClientError> + From<std::io::Error>, 
8{
9    type Error = E;
10
11    async fn upload_batch_file_path(
12        &self,
13        file_path: &Path,
14    ) -> Result<OpenAIFile, Self::Error> {
15        info!("uploading batch file at path={:?} to online", file_path);
16
17        let create_file_request = CreateFileRequest {
18            file:    file_path.into(),
19            purpose: FilePurpose::Batch,
20        };
21
22        // similarly map the openai error
23        let file = self.files().create(create_file_request).await
24            .map_err(|api_err| E::from(OpenAIClientError::OpenAIError(api_err)))?;
25
26        Ok(file)
27    }
28}
29
30#[async_trait]
31impl<E: Debug + Send + Sync + From<std::io::Error> + From<OpenAIClientError>> UploadBatchFileExt for OpenAIClientHandle<E> {}
32
33#[cfg(test)]
34mod upload_batch_file_core_tests {
35    use super::*;
36    use futures::executor::block_on;
37    use std::path::Path;
38    use std::sync::Arc;
39    use tempfile::{NamedTempFile, tempdir};
40    use tracing::{debug, error, info, trace, warn};
41
42    /// Exhaustive test suite for the `UploadBatchFileCore` implementation on `OpenAIClientHandle`.
43    /// We use the mock client to simulate various scenarios (success, error, invalid input, etc).
44    #[traced_test]
45    async fn test_upload_batch_file_path_success() {
46        info!("Beginning test_upload_batch_file_path_success");
47        trace!("Constructing mock client...");
48        let mock_client = MockLanguageModelClientBuilder::<MockBatchClientError>::default()
49            .build()
50            .unwrap();
51        debug!("Mock client built: {:?}", mock_client);
52
53        trace!("Creating a temporary file to simulate a local batch file...");
54        let temp_file = NamedTempFile::new().expect("Failed to create temp file");
55        debug!("Temp file path: {:?}", temp_file.path());
56
57        trace!("Calling upload_batch_file_path with a valid file path");
58        let result = mock_client.upload_batch_file_path(temp_file.path()).await;
59        debug!("Result from upload_batch_file_path: {:?}", result);
60
61        // For a valid file path, we expect an Ok result (unless the mock is forced to fail).
62        assert!(
63            result.is_ok(),
64            "Expected upload_batch_file_path to succeed with a valid file path"
65        );
66        let uploaded_file = result.unwrap();
67        debug!("Uploaded file response: {:?}", uploaded_file);
68        info!("test_upload_batch_file_path_success passed.");
69    }
70
71    #[traced_test]
72    async fn test_upload_batch_file_path_invalid_file_path() {
73        info!("Beginning test_upload_batch_file_path_invalid_file_path");
74        trace!("Constructing mock client...");
75        let mock_client = MockLanguageModelClientBuilder::<MockBatchClientError>::default()
76            .build()
77            .unwrap();
78        debug!("Mock client built: {:?}", mock_client);
79
80        // Provide an invalid path that likely doesn't exist
81        let invalid_path = Path::new("/this/path/does/not/exist");
82        trace!("Calling upload_batch_file_path with an invalid path: {:?}", invalid_path);
83        let result = mock_client.upload_batch_file_path(invalid_path).await;
84        debug!("Result from upload_batch_file_path: {:?}", result);
85
86        // We expect this to fail (std::io::Error or something else).
87        assert!(
88            result.is_err(),
89            "Expected upload_batch_file_path to fail with a non-existent file path"
90        );
91        info!("test_upload_batch_file_path_invalid_file_path passed.");
92    }
93
94    #[traced_test]
95    async fn test_upload_batch_file_path_openai_api_error() {
96        info!("Beginning test_upload_batch_file_path_openai_api_error");
97        trace!("Constructing mock client that simulates an OpenAI error...");
98
99        let mock_client = MockLanguageModelClientBuilder::<MockBatchClientError>::default()
100            .fail_on_file_create_openai_error(true)
101            .build()
102            .unwrap();
103
104        debug!("Mock client built: {:?}", mock_client);
105
106        let temp_file = NamedTempFile::new().expect("Failed to create temp file");
107        debug!("Temp file path: {:?}", temp_file.path());
108
109        trace!("Calling upload_batch_file_path expecting an API error scenario...");
110        let result = mock_client.upload_batch_file_path(temp_file.path()).await;
111        debug!("Result from upload_batch_file_path: {:?}", result);
112
113        // We expect an Err for an OpenAI error
114        assert!(
115            result.is_err(),
116            "Expected upload_batch_file_path to return an error due to OpenAI API error"
117        );
118        info!("test_upload_batch_file_path_openai_api_error passed.");
119    }
120
121    #[traced_test]
122    async fn test_upload_batch_file_path_other_error() {
123        info!("Beginning test_upload_batch_file_path_other_error");
124        trace!("Constructing mock client that simulates a different kind of error...");
125
126        let mock_client = MockLanguageModelClientBuilder::<MockBatchClientError>::default()
127            // We specifically set fail_on_file_create_other_error so that the mock
128            // forcibly returns an IO error on upload.
129            .fail_on_file_create_other_error(true)
130            .build()
131            .unwrap();
132
133        debug!("Mock client built: {:?}", mock_client);
134
135        let temp_file = NamedTempFile::new().expect("Failed to create temp file");
136        debug!("Temp file path: {:?}", temp_file.path());
137
138        trace!("Calling upload_batch_file_path expecting a non-OpenAI error scenario...");
139        let result = mock_client.upload_batch_file_path(temp_file.path()).await;
140        debug!("Result from upload_batch_file_path: {:?}", result);
141
142        // We expect an Err for a simulated non-OpenAI error (IO error).
143        assert!(
144            result.is_err(),
145            "Expected upload_batch_file_path to return a non-OpenAI error scenario"
146        );
147        info!("test_upload_batch_file_path_other_error passed.");
148    }
149}