Skip to content
Merged
Show file tree
Hide file tree
Changes from 5 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
11 changes: 2 additions & 9 deletions daemon/cmd/integration_runner/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -362,15 +362,8 @@ func main() {
ctx.Settings["newrelic.loglevel"] = *flagLoglevel
}

if false == *flagOpcacheOff {
// PHP Modules common to all tests
ctx.Settings["zend_extension"] = "opcache.so"

// PHP INI values common to all tests
// These settings can be overwritten by adding new values to the INI block
ctx.Settings["opcache.enable"] = "1"
ctx.Settings["opcache.enable_cli"] = "1"
}
ctx.OPCacheModuleLoaded = integration.GetOPCacheModuleLoaded(*flagPHP, *flagCGI)
ctx.UseOPCache = !*flagOpcacheOff

// If the user provided a custom agent extension, use it.
if len(*flagAgent) > 0 {
Expand Down
14 changes: 8 additions & 6 deletions daemon/internal/newrelic/integration/context.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,14 @@ import (
)

type Context struct {
PHP string // path to the PHP CLI executable
CGI string // path to the PHP CGI executable
Valgrind string // path to the Valgrind executable, or empty if disabled
Env map[string]string // environment variables to pass to each test
Settings map[string]string // settings to pass to each test
Timeout time.Duration // maximum test duration
PHP string // path to the PHP CLI executable
CGI string // path to the PHP CGI executable
Valgrind string // path to the Valgrind executable, or empty if disabled
Env map[string]string // environment variables to pass to each test
Settings map[string]string // settings to pass to each test
Timeout time.Duration // maximum test duration
OPCacheModuleLoaded map[string]bool // map of PHP and CGI to OPcache default loaded status
UseOPCache bool // whether to use OPcache in tests
}

func NewContext(php, cgi string) *Context {
Expand Down
23 changes: 22 additions & 1 deletion daemon/internal/newrelic/integration/test.go
Original file line number Diff line number Diff line change
Expand Up @@ -214,7 +214,28 @@ func (t *Test) MakeRun(ctx *Context) (Tx, error) {
}
}

settings = merge(settings, t.PhpModules)
// Make a copy of t.PhpModules and remove any entries containing "opcache.so"
// if opcache.so is loaded by default
//
// three cases:
// 1. C test - no opcache.so needed as PHP is not going to be run
// 2. Web test and php-cgi has opcache.so loaded by default - remove any PHPMODULE spec for opcache.so
// 3. PHP test and php has opcache.so loaded by default - remove any PHPMODULE spec for opcache.so
phpModulesCopy := make(map[string]string)
if !t.IsC() {
if (t.IsWeb() && ctx.OPCacheModuleLoaded[ctx.CGI]) ||
(ctx.OPCacheModuleLoaded[ctx.PHP]) {
for k, v := range t.PhpModules {
if !strings.Contains(v, "opcache.so") {
phpModulesCopy[k] = v
}
}
}
} else {
fmt.Printf("ERROR - UNEXPECTED - Running C test: %s\n", t.Path)
os.Exit(1)
}
settings = merge(settings, phpModulesCopy)

if t.IsC() {
return CTx(ScriptFile(t.Path), t.Env, settings, headers, ctx)
Expand Down
76 changes: 72 additions & 4 deletions daemon/internal/newrelic/integration/transaction.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,9 +46,43 @@ func PhpTx(src Script, env, settings map[string]string, ctx *Context) (Tx, error
// Note: file path must be relative to the working directory.
var txn Tx

args := phpArgs(nil, filepath.Base(src.Name()), false, settings)
// Make a copy of settings to avoid mutating the original map
phpSettings := make(map[string]string, len(settings))
setOPCacheEnable := true
setOPCacheEnableCLI := true
for k, v := range settings {
phpSettings[k] = v

// see if settings affect opcache config
// if so then we will not set config below
if k == "opcache.enable" {
setOPCacheEnable = false
} else if k == "opcache.enable_cli" {
setOPCacheEnableCLI = false
}
}
if ctx.UseOPCache {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ctx.UseOPCache is actually the negation of the value of the --opcacheoff flag passed to integration_runner, which is false by default. This means that this branch is the default behavior. This also means that that --opcacheoff does not affect presence of opcache.so module.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That seems correct.

if !ctx.OPCacheModuleLoaded[ctx.CGI] {
phpSettings["zend_extension"] = "opcache.so"
}
if setOPCacheEnable {
phpSettings["opcache.enable"] = "1"
}
if setOPCacheEnableCLI {
phpSettings["opcache.enable_cli"] = "1"
}
} else {
if setOPCacheEnable {
phpSettings["opcache.enable"] = "0"
}
if setOPCacheEnableCLI {
phpSettings["opcache.enable_cli"] = "0"
}
}

args := phpArgs(nil, filepath.Base(src.Name()), false, phpSettings)

if ctx.Valgrind != "" && settings["newrelic.appname"] != "skipif" {
if ctx.Valgrind != "" && phpSettings["newrelic.appname"] != "skipif" {
txn = &ValgrindCLI{
CLI: CLI{
Path: ctx.PHP,
Expand Down Expand Up @@ -106,14 +140,48 @@ func CgiTx(src Script, env, settings map[string]string, headers http.Header, ctx
return nil, fmt.Errorf("unable to create cgi request: %v", err)
}

// Make a copy of settings to avoid mutating the original map
cgiSettings := make(map[string]string, len(settings))
setOPCacheEnable := true
setOPCacheEnableCLI := true
for k, v := range settings {
cgiSettings[k] = v

// see if settings affect opcache config
// if so then we will not set config below
if k == "opcache.enable" {
setOPCacheEnable = false
} else if k == "opcache.enable_cli" {
setOPCacheEnableCLI = false
}
}
if ctx.UseOPCache {
if !ctx.OPCacheModuleLoaded[ctx.CGI] {
cgiSettings["zend_extension"] = "opcache.so"
}
if setOPCacheEnable {
cgiSettings["opcache.enable"] = "1"
}
if setOPCacheEnableCLI {
cgiSettings["opcache.enable_cli"] = "1"
}
} else {
if setOPCacheEnable {
cgiSettings["opcache.enable"] = "0"
}
if setOPCacheEnableCLI {
cgiSettings["opcache.enable_cli"] = "0"
}
}

if ctx.Valgrind != "" {
tx := &ValgrindCGI{
CGI: CGI{
request: req,
handler: &cgi.Handler{
Path: ctx.CGI,
Dir: src.Dir(),
Args: phpArgs(nil, "", false, settings),
Args: phpArgs(nil, "", false, cgiSettings),
},
},
Valgrind: ctx.Valgrind,
Expand Down Expand Up @@ -144,7 +212,7 @@ func CgiTx(src Script, env, settings map[string]string, headers http.Header, ctx
handler: &cgi.Handler{
Path: ctx.CGI,
Dir: src.Dir(),
Args: phpArgs(nil, "", false, settings),
Args: phpArgs(nil, "", false, cgiSettings),
},
}
tx.handler.Env = append(tx.handler.Env,
Expand Down
28 changes: 28 additions & 0 deletions daemon/internal/newrelic/integration/util.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@
package integration

import (
"bytes"
"fmt"
"os"
"os/exec"
)

Expand All @@ -31,3 +33,29 @@ func GetAgentVersion(agent_extension string) string {
}
return string(output)
}

func IsOPcacheLoaded(php_executable string) bool {
fmt.Printf("Checking if OPcache is loaded using %s\n", php_executable)
cmd := exec.Command(php_executable, "-m")

output, err := cmd.Output()

if err != nil {
fmt.Printf("Failed to check if OPcache is loaded: %v\n", err)
os.Exit(1)
}

// Check if "Zend OPcache" is in the output
return bytes.Contains(output, []byte("Zend OPcache"))
}

func GetOPCacheModuleLoaded(php, cgi string) map[string]bool {
result := make(map[string]bool)

result[php] = IsOPcacheLoaded(php)
result[cgi] = IsOPcacheLoaded(cgi)

fmt.Printf("OPcache default loaded status: %+v\n", result)

return result
}