132 lines
4.3 KiB
Go
132 lines
4.3 KiB
Go
package template
|
|
|
|
import (
|
|
"bytes"
|
|
"testing"
|
|
"text/template"
|
|
|
|
"github.com/ollama/ollama/api"
|
|
)
|
|
|
|
func TestRewritePropertiesCheck(t *testing.T) {
|
|
makeToolWithProps := func(props *api.ToolProperties) api.Tool {
|
|
return api.Tool{
|
|
Type: "function",
|
|
Function: api.ToolFunction{
|
|
Name: "test",
|
|
Description: "test function",
|
|
Parameters: api.NewToolFunctionParametersWithProps("object", nil, props),
|
|
},
|
|
}
|
|
}
|
|
|
|
tests := []struct {
|
|
name string
|
|
template string
|
|
data interface{}
|
|
expected string
|
|
}{
|
|
{
|
|
name: "if statement with Properties gets rewritten to HasProperties",
|
|
template: `{{if .Function.Parameters.Properties}}Has props{{else}}No props{{end}}`,
|
|
data: makeToolWithProps(nil),
|
|
expected: "No props", // Should use HasProperties which returns false for empty
|
|
},
|
|
{
|
|
name: "if statement with Properties and non-empty properties",
|
|
template: `{{if .Function.Parameters.Properties}}Has props{{else}}No props{{end}}`,
|
|
data: makeToolWithProps(func() *api.ToolProperties {
|
|
p := api.NewToolProperties()
|
|
p.Set("test", api.ToolProperty{Type: api.PropertyType{"string"}})
|
|
return p
|
|
}()),
|
|
expected: "Has props", // Should use HasProperties which returns true
|
|
},
|
|
{
|
|
name: "range over Properties should not be rewritten",
|
|
template: `{{range $k, $v := .Function.Parameters.Properties}}{{$k}} {{end}}`,
|
|
data: makeToolWithProps(func() *api.ToolProperties {
|
|
p := api.NewToolProperties()
|
|
p.Set("foo", api.ToolProperty{Type: api.PropertyType{"string"}})
|
|
p.Set("bar", api.ToolProperty{Type: api.PropertyType{"number"}})
|
|
return p
|
|
}()),
|
|
expected: "foo bar ", // Should still use Properties() for ranging
|
|
},
|
|
{
|
|
name: "complex template with both if and range",
|
|
template: `{{if .Function.Parameters.Properties}}Args:
|
|
{{range $k, $v := .Function.Parameters.Properties}} {{$k}}
|
|
{{end}}{{else}}No args{{end}}`,
|
|
data: makeToolWithProps(func() *api.ToolProperties {
|
|
p := api.NewToolProperties()
|
|
p.Set("location", api.ToolProperty{Type: api.PropertyType{"string"}})
|
|
return p
|
|
}()),
|
|
expected: "Args:\n location\n",
|
|
},
|
|
{
|
|
name: "if with and condition",
|
|
template: `{{if and .Function.Parameters.Properties (gt (len .Function.Parameters.Properties) 0)}}yes{{else}}no{{end}}`,
|
|
data: makeToolWithProps(nil),
|
|
expected: "no", // Empty, so HasProperties returns false
|
|
},
|
|
{
|
|
name: "len function on Properties gets rewritten to Len method",
|
|
template: `{{len .Function.Parameters.Properties}}`,
|
|
data: makeToolWithProps(nil),
|
|
expected: "0", // Empty properties should have length 0
|
|
},
|
|
{
|
|
name: "len function on non-empty Properties",
|
|
template: `{{len .Function.Parameters.Properties}}`,
|
|
data: makeToolWithProps(func() *api.ToolProperties {
|
|
p := api.NewToolProperties()
|
|
p.Set("foo", api.ToolProperty{Type: api.PropertyType{"string"}})
|
|
p.Set("bar", api.ToolProperty{Type: api.PropertyType{"number"}})
|
|
return p
|
|
}()),
|
|
expected: "2", // Two properties
|
|
},
|
|
{
|
|
name: "nested len in and/gt (gpt-oss pattern)",
|
|
template: `{{if and .Function.Parameters.Properties (gt (len .Function.Parameters.Properties) 0)}}has props{{else}}no props{{end}}`,
|
|
data: makeToolWithProps(nil),
|
|
expected: "no props", // Empty, so both checks should be false
|
|
},
|
|
{
|
|
name: "nested len in and/gt with properties",
|
|
template: `{{if and .Function.Parameters.Properties (gt (len .Function.Parameters.Properties) 0)}}has props{{else}}no props{{end}}`,
|
|
data: makeToolWithProps(func() *api.ToolProperties {
|
|
p := api.NewToolProperties()
|
|
p.Set("test", api.ToolProperty{Type: api.PropertyType{"string"}})
|
|
return p
|
|
}()),
|
|
expected: "has props", // Has properties, both checks should be true
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
// Use text/template directly and call rewritePropertiesCheck
|
|
tmpl, err := template.New("test").Parse(tt.template)
|
|
if err != nil {
|
|
t.Fatalf("Failed to parse template: %v", err)
|
|
}
|
|
|
|
// Apply the rewrite
|
|
rewritePropertiesCheck(tmpl)
|
|
|
|
var buf bytes.Buffer
|
|
err = tmpl.Execute(&buf, tt.data)
|
|
if err != nil {
|
|
t.Fatalf("Failed to execute template: %v", err)
|
|
}
|
|
|
|
if buf.String() != tt.expected {
|
|
t.Errorf("Expected %q, got %q", tt.expected, buf.String())
|
|
}
|
|
})
|
|
}
|
|
}
|