test_that("Text completion functions work correctly", { # Test with actual model if available possible_paths <- c( "tinyllama-1.1b-chat-v1.0.Q4_K_M.gguf", "models/tinyllama-1.1b-chat-v1.0.Q4_K_M.gguf", file.path(Sys.getenv("HOME"), ".cache", "edgemodelr", "tinyllama-1.1b-chat-v1.0.Q4_K_M.gguf") ) model_path <- NULL for (path in possible_paths) { if (file.exists(path)) { model_path <- path break } } if (!is.null(model_path)) { test_that("edge_completion basic functionality", { # Load fresh model for this test ctx <- edge_load_model(model_path, n_ctx = 512) # Test basic completion result <- edge_completion(ctx, "Hello", n_predict = 5) expect_true(is.character(result)) expect_true(nchar(result) > 0) expect_true(nchar(result) > nchar("Hello")) edge_free_model(ctx) }) test_that("edge_completion with different prompts", { # Load fresh model for this test ctx <- edge_load_model(model_path, n_ctx = 512) # Test various prompts prompts <- c( "The capital of France is", "Once upon a time", "2 + 2 =", "What is" ) for (prompt in prompts) { result <- edge_completion(ctx, prompt, n_predict = 10) expect_true(is.character(result)) expect_true(nchar(result) > nchar(prompt)) expect_true(startsWith(result, prompt)) } edge_free_model(ctx) }) test_that("edge_completion with different n_predict values", { # Load fresh model for this test ctx <- edge_load_model(model_path, n_ctx = 512) prompt <- "Hello world" # Short completion result1 <- edge_completion(ctx, prompt, n_predict = 1) expect_true(is.character(result1)) # Medium completion result2 <- edge_completion(ctx, prompt, n_predict = 10) expect_true(is.character(result2)) expect_true(nchar(result2) >= nchar(result1)) # Longer completion result3 <- edge_completion(ctx, prompt, n_predict = 20) expect_true(is.character(result3)) expect_true(nchar(result3) >= nchar(result2)) edge_free_model(ctx) }) test_that("edge_completion with empty prompt", { # Load fresh model for this test ctx <- edge_load_model(model_path, n_ctx = 512) # Empty string should still generate text result <- edge_completion(ctx, "", n_predict = 5) expect_true(is.character(result)) expect_true(nchar(result) > 0) edge_free_model(ctx) }) test_that("edge_completion with long prompt", { # Load fresh model for this test ctx <- edge_load_model(model_path, n_ctx = 512) # Test with a longer prompt long_prompt <- paste(rep("This is a test sentence.", 10), collapse = " ") result <- edge_completion(ctx, long_prompt, n_predict = 5) expect_true(is.character(result)) expect_true(startsWith(result, long_prompt)) edge_free_model(ctx) }) test_that("edge_completion parameter validation", { # Load fresh model for this test ctx <- edge_load_model(model_path, n_ctx = 512) # Test invalid prompts - these should error expect_error(edge_completion(ctx, NULL)) expect_error(edge_completion(ctx, c("Hello", "World"))) expect_error(edge_completion(ctx, 123)) expect_error(edge_completion(ctx, list())) # Test edge case n_predict values - implementation handles these gracefully result1 <- edge_completion(ctx, "Hello", n_predict = -1) expect_true(is.character(result1)) result2 <- edge_completion(ctx, "Hello", n_predict = 0) expect_true(is.character(result2)) # Test invalid n_predict types - these should error expect_error(edge_completion(ctx, "Hello", n_predict = "invalid")) expect_error(edge_completion(ctx, "Hello", n_predict = NULL)) # Test edge case temperature values - implementation handles these gracefully result3 <- edge_completion(ctx, "Hello", temperature = -0.1) expect_true(is.character(result3)) # Test invalid temperature types - these should error expect_error(edge_completion(ctx, "Hello", temperature = "invalid")) expect_error(edge_completion(ctx, "Hello", temperature = NULL)) # Test edge case top_p values - implementation handles these gracefully result4 <- edge_completion(ctx, "Hello", top_p = -0.1) expect_true(is.character(result4)) # Test boundary top_p values result5 <- edge_completion(ctx, "Hello", top_p = 1.1) # May be clamped to 1.0 expect_true(is.character(result5)) # Test invalid top_p types - these should error expect_error(edge_completion(ctx, "Hello", top_p = "invalid")) expect_error(edge_completion(ctx, "Hello", top_p = NULL)) edge_free_model(ctx) }) test_that("edge_completion with special characters", { # Load fresh model for this test ctx <- edge_load_model(model_path, n_ctx = 512) # Test with various special characters special_prompts <- c( "Hello! How are you?", "What is 2+2=", "The price is $100.", "Email: user@example.com", "Path: C:\\Users\\test" ) for (prompt in special_prompts) { result <- edge_completion(ctx, prompt, n_predict = 5) expect_true(is.character(result)) expect_true(startsWith(result, prompt)) } edge_free_model(ctx) }) test_that("edge_completion with different temperature settings", { # Load fresh model for this test ctx <- edge_load_model(model_path, n_ctx = 512) prompt <- "The weather today is" # Low temperature (more deterministic) result_low <- edge_completion(ctx, prompt, n_predict = 10, temperature = 0.1) expect_true(is.character(result_low)) expect_true(startsWith(result_low, prompt)) # High temperature (more random) result_high <- edge_completion(ctx, prompt, n_predict = 10, temperature = 1.0) expect_true(is.character(result_high)) expect_true(startsWith(result_high, prompt)) # Very high temperature (maximum randomness) result_max <- edge_completion(ctx, prompt, n_predict = 10, temperature = 2.0) expect_true(is.character(result_max)) expect_true(startsWith(result_max, prompt)) edge_free_model(ctx) }) test_that("edge_completion with different top_p settings", { # Load fresh model for this test ctx <- edge_load_model(model_path, n_ctx = 512) prompt <- "The answer is" # Low top_p (nucleus sampling with small nucleus) result_low <- edge_completion(ctx, prompt, n_predict = 5, top_p = 0.1) expect_true(is.character(result_low)) expect_true(startsWith(result_low, prompt)) # Medium top_p result_med <- edge_completion(ctx, prompt, n_predict = 5, top_p = 0.5) expect_true(is.character(result_med)) expect_true(startsWith(result_med, prompt)) # High top_p (almost no nucleus filtering) result_high <- edge_completion(ctx, prompt, n_predict = 5, top_p = 0.95) expect_true(is.character(result_high)) expect_true(startsWith(result_high, prompt)) edge_free_model(ctx) }) test_that("edge_completion edge cases", { # Load fresh model for this test ctx <- edge_load_model(model_path, n_ctx = 512) # Very large n_predict result_large <- edge_completion(ctx, "Hello", n_predict = 500) expect_true(is.character(result_large)) expect_true(startsWith(result_large, "Hello")) # Extreme temperature values result_zero_temp <- edge_completion(ctx, "Test", n_predict = 5, temperature = 0.001) expect_true(is.character(result_zero_temp)) # Extreme top_p values result_low_top_p <- edge_completion(ctx, "Test", n_predict = 5, top_p = 0.01) expect_true(is.character(result_low_top_p)) result_high_top_p <- edge_completion(ctx, "Test", n_predict = 5, top_p = 0.99) expect_true(is.character(result_high_top_p)) edge_free_model(ctx) }) test_that("edge_completion with Unicode and international text", { # Load fresh model for this test ctx <- edge_load_model(model_path, n_ctx = 512) # Test with Unicode characters unicode_prompts <- c( "Hello 世界", # Chinese "Bonjour le monde", # French "Hola mundo", # Spanish "Здравствуй мир", # Russian "こんにちは世界", # Japanese "🌍 World emoji" # Emoji ) for (prompt in unicode_prompts) { tryCatch({ result <- edge_completion(ctx, prompt, n_predict = 5) expect_true(is.character(result)) expect_true(nchar(result) > 0) }, error = function(e) { # Some models may not handle Unicode well - accept any error message expect_true(nchar(e$message) > 0) }) } edge_free_model(ctx) }) test_that("edge_completion stress tests", { # Load fresh model for this test ctx <- edge_load_model(model_path, n_ctx = 512) # Very long prompt (near context limit) long_prompt <- paste(rep("This is a test sentence with multiple words. ", 50), collapse = "") tryCatch({ result <- edge_completion(ctx, long_prompt, n_predict = 5) expect_true(is.character(result)) }, error = function(e) { # May fail if prompt exceeds context window - accept any error message expect_true(nchar(e$message) > 0) }) # Repeated generations (memory leak test) for (i in 1:10) { result <- edge_completion(ctx, "Quick test", n_predict = 3) expect_true(is.character(result)) expect_true(nchar(result) > 0) } edge_free_model(ctx) }) test_that("edge_completion consistency", { # Load fresh model for this test ctx <- edge_load_model(model_path, n_ctx = 512) # Test that the same prompt produces consistent results (within reason) prompt <- "The quick brown fox" results <- replicate(3, edge_completion(ctx, prompt, n_predict = 10, temperature = 0.1)) # All should be strings starting with the prompt for (result in results) { expect_true(is.character(result)) expect_true(startsWith(result, prompt)) } # With low temperature, results should be more similar # (though not necessarily identical due to sampling) expect_true(length(unique(results)) <= 3) # At most 3 different results edge_free_model(ctx) }) # Test that multiple completions work in sequence test_that("Sequential completions work correctly", { # Load fresh model for this test ctx <- edge_load_model(model_path, n_ctx = 512) prompts <- c("Hello", "World", "Test", "Final") for (prompt in prompts) { result <- edge_completion(ctx, prompt, n_predict = 3) expect_true(is.character(result)) expect_true(startsWith(result, prompt)) } edge_free_model(ctx) }) } else { skip("No test model available for text completion tests") } test_that("edge_completion error handling", { # Test with invalid context expect_error( edge_completion(NULL, "Hello", n_predict = 5) ) expect_error( edge_completion("invalid", "Hello", n_predict = 5) ) expect_error( edge_completion(123, "Hello", n_predict = 5) ) expect_error( edge_completion(list(), "Hello", n_predict = 5) ) # Test with missing arguments expect_error(edge_completion()) expect_error(edge_completion(NULL)) # Test with freed model context possible_paths <- c( "tinyllama-1.1b-chat-v1.0.Q4_K_M.gguf", "models/tinyllama-1.1b-chat-v1.0.Q4_K_M.gguf", file.path(Sys.getenv("HOME"), ".cache", "edgemodelr", "tinyllama-1.1b-chat-v1.0.Q4_K_M.gguf") ) model_path <- NULL for (path in possible_paths) { if (file.exists(path)) { model_path <- path break } } if (!is.null(model_path)) { ctx <- edge_load_model(model_path, n_ctx = 256) edge_free_model(ctx) # Note: In current implementation, freed contexts may still be valid # This is acceptable behavior for this R package } }) # Test boundary conditions and edge cases test_that("edge_completion boundary conditions", { possible_paths <- c( "tinyllama-1.1b-chat-v1.0.Q4_K_M.gguf", "models/tinyllama-1.1b-chat-v1.0.Q4_K_M.gguf", file.path(Sys.getenv("HOME"), ".cache", "edgemodelr", "tinyllama-1.1b-chat-v1.0.Q4_K_M.gguf") ) model_path <- NULL for (path in possible_paths) { if (file.exists(path)) { model_path <- path break } } if (!is.null(model_path)) { ctx <- edge_load_model(model_path, n_ctx = 512) # Test minimum n_predict result_min <- edge_completion(ctx, "Hello", n_predict = 1) expect_true(is.character(result_min)) expect_true(nchar(result_min) > nchar("Hello")) # Test various prompt lengths short_prompt <- "Hi" medium_prompt <- "This is a medium length prompt with several words" long_prompt <- paste(rep("word", 100), collapse = " ") result_short <- edge_completion(ctx, short_prompt, n_predict = 5) result_medium <- edge_completion(ctx, medium_prompt, n_predict = 5) expect_true(is.character(result_short)) expect_true(is.character(result_medium)) expect_true(startsWith(result_short, short_prompt)) expect_true(startsWith(result_medium, medium_prompt)) # Long prompt may hit context limits tryCatch({ result_long <- edge_completion(ctx, long_prompt, n_predict = 5) expect_true(is.character(result_long)) }, error = function(e) { # Expected for very long prompts expect_true(TRUE) }) # Test whitespace handling whitespace_prompts <- c( " ", # Single space "\n", # Newline "\t", # Tab " ", # Multiple spaces "Hello\nWorld", # Prompt with newline "Hello\tWorld" # Prompt with tab ) for (prompt in whitespace_prompts) { result <- edge_completion(ctx, prompt, n_predict = 3) expect_true(is.character(result)) expect_true(nchar(result) > 0) } edge_free_model(ctx) } else { skip("No test model available for boundary condition tests") } }) })