-
Notifications
You must be signed in to change notification settings - Fork 815
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[ci][win32] Add basic integration tests (#2725)
For the following Windows checks: * iis * sqlserver * windows_service * wmi_check The tests are meant to run on AppVeyor and make heavy use of the environment provided by AppVeyor. They would most likely fail if run on a local dev environment on Windows.
- Loading branch information
1 parent
489902e
commit e4a22e5
Showing
7 changed files
with
355 additions
and
82 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,86 @@ | ||
# 3p | ||
from nose.plugins.attrib import attr | ||
|
||
# project | ||
from tests.checks.common import AgentCheckTest | ||
|
||
MINIMAL_INSTANCE = { | ||
'host': '.', | ||
} | ||
|
||
INSTANCE = { | ||
'host': '.', | ||
'sites': ['Default Web Site', 'Test-Website-1', 'Non Existing Website'], | ||
} | ||
|
||
INVALID_HOST_INSTANCE = { | ||
'host': 'nonexistinghost' | ||
} | ||
|
||
|
||
@attr('windows') | ||
@attr(requires='windows') | ||
class IISTest(AgentCheckTest): | ||
CHECK_NAME = 'iis' | ||
|
||
IIS_METRICS = ( | ||
'iis.uptime', | ||
# Network | ||
'iis.net.bytes_sent', | ||
'iis.net.bytes_rcvd', | ||
'iis.net.bytes_total', | ||
'iis.net.num_connections', | ||
'iis.net.files_sent', | ||
'iis.net.files_rcvd', | ||
'iis.net.connection_attempts', | ||
# HTTP Methods | ||
'iis.httpd_request_method.get', | ||
'iis.httpd_request_method.post', | ||
'iis.httpd_request_method.head', | ||
'iis.httpd_request_method.put', | ||
'iis.httpd_request_method.delete', | ||
'iis.httpd_request_method.options', | ||
'iis.httpd_request_method.trace', | ||
# Errors | ||
'iis.errors.not_found', | ||
'iis.errors.locked', | ||
# Users | ||
'iis.users.anon', | ||
'iis.users.nonanon', | ||
# Requests | ||
'iis.requests.cgi', | ||
'iis.requests.isapi', | ||
) | ||
|
||
def test_basic_check(self): | ||
self.run_check_twice({'instances': [MINIMAL_INSTANCE]}) | ||
|
||
for metric in self.IIS_METRICS: | ||
self.assertMetric(metric, tags=[], count=1) | ||
|
||
self.assertServiceCheckOK('iis.site_up', tags=["site:{0}".format('Total')], count=1) | ||
self.coverage_report() | ||
|
||
def test_check_on_specific_websites(self): | ||
self.run_check_twice({'instances': [INSTANCE]}) | ||
|
||
site_tags = ['Default_Web_Site', 'Test_Website_1'] | ||
for metric in self.IIS_METRICS: | ||
for site_tag in site_tags: | ||
self.assertMetric(metric, tags=["site:{0}".format(site_tag)], count=1) | ||
|
||
self.assertServiceCheckOK('iis.site_up', | ||
tags=["site:{0}".format('Default_Web_Site')], count=1) | ||
self.assertServiceCheckOK('iis.site_up', | ||
tags=["site:{0}".format('Test_Website_1')], count=1) | ||
self.assertServiceCheckCritical('iis.site_up', | ||
tags=["site:{0}".format('Non_Existing_Website')], count=1) | ||
|
||
self.coverage_report() | ||
|
||
def test_service_check_with_invalid_host(self): | ||
self.run_check({'instances': [INVALID_HOST_INSTANCE]}) | ||
|
||
self.assertServiceCheckCritical('iis.site_up', tags=["site:{0}".format('Total')]) | ||
|
||
self.coverage_report() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,122 @@ | ||
# stdlib | ||
import copy | ||
|
||
# 3p | ||
from nose.plugins.attrib import attr | ||
|
||
# project | ||
from tests.checks.common import AgentCheckTest | ||
|
||
|
||
""" | ||
Runs against AppVeyor's SQLServer setups with their default configurations | ||
""" | ||
|
||
CONFIG = { | ||
'init_config': { | ||
'custom_metrics': [ | ||
{ | ||
'name': 'sqlserver.clr.execution', | ||
'type': 'gauge', | ||
'counter_name': 'CLR Execution', | ||
}, | ||
{ | ||
'name': 'sqlserver.exec.in_progress', | ||
'type': 'gauge', | ||
'counter_name': 'OLEDB calls', | ||
'instance_name': 'Cumulative execution time (ms) per second', | ||
}, | ||
{ | ||
'name': 'sqlserver.db.commit_table_entries', | ||
'type': 'gauge', | ||
'counter_name': 'Log Flushes/sec', | ||
'instance_name': 'ALL', | ||
'tag_by': 'db', | ||
}, | ||
], | ||
} | ||
} | ||
|
||
SQL2008_INSTANCE = { | ||
'host': '(local)\SQL2008R2SP2', | ||
'username': 'sa', | ||
'password': 'Password12!', | ||
} | ||
|
||
SQL2012_INSTANCE = { | ||
'host': '(local)\SQL2012SP1', | ||
'username': 'sa', | ||
'password': 'Password12!', | ||
} | ||
|
||
SQL2014_INSTANCE = { | ||
'host': '(local)\SQL2014', | ||
'username': 'sa', | ||
'password': 'Password12!', | ||
} | ||
|
||
EXPECTED_METRICS = [ | ||
'sqlserver.buffer.cache_hit_ratio', | ||
'sqlserver.buffer.page_life_expectancy', | ||
'sqlserver.stats.batch_requests', | ||
'sqlserver.stats.sql_compilations', | ||
'sqlserver.stats.sql_recompilations', | ||
'sqlserver.stats.connections', | ||
'sqlserver.stats.lock_waits', | ||
'sqlserver.access.page_splits', | ||
'sqlserver.stats.procs_blocked', | ||
'sqlserver.buffer.checkpoint_pages', | ||
] | ||
|
||
|
||
@attr('windows') | ||
@attr(requires='windows') | ||
class SQLServerTest(AgentCheckTest): | ||
CHECK_NAME = 'sqlserver' | ||
|
||
def _test_check(self, config): | ||
self.run_check_twice(config, force_reload=True) | ||
|
||
# Check our custom metrics | ||
self.assertMetric('sqlserver.clr.execution') | ||
self.assertMetric('sqlserver.exec.in_progress') | ||
# Make sure the ALL custom metric is tagged by db | ||
self.assertMetricTagPrefix('sqlserver.db.commit_table_entries', tag_prefix='db') | ||
|
||
for metric in EXPECTED_METRICS: | ||
self.assertMetric(metric, count=1) | ||
|
||
self.assertServiceCheckOK('sqlserver.can_connect', | ||
tags=['host:{}'.format(config['instances'][0]['host']), 'db:master']) | ||
|
||
self.coverage_report() | ||
|
||
def test_check_2008(self): | ||
config = copy.deepcopy(CONFIG) | ||
config['instances'] = [SQL2008_INSTANCE] | ||
self._test_check(config) | ||
|
||
def test_check_2012(self): | ||
config = copy.deepcopy(CONFIG) | ||
config['instances'] = [SQL2012_INSTANCE] | ||
self._test_check(config) | ||
|
||
def test_check_2014(self): | ||
config = copy.deepcopy(CONFIG) | ||
config['instances'] = [SQL2014_INSTANCE] | ||
self._test_check(config) | ||
|
||
def test_check_no_connection(self): | ||
config = copy.deepcopy(CONFIG) | ||
config['instances'] = [{ | ||
'host': '(local)\SQL2012SP1', | ||
'username': 'sa', | ||
'password': 'InvalidPassword', | ||
'timeout': 1, | ||
}] | ||
|
||
with self.assertRaisesRegexp(Exception, 'Unable to connect to SQL Server'): | ||
self.run_check(config, force_reload=True) | ||
|
||
self.assertServiceCheckCritical('sqlserver.can_connect', | ||
tags=['host:(local)\SQL2012SP1', 'db:master']) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
# 3p | ||
from nose.plugins.attrib import attr | ||
|
||
# project | ||
from tests.checks.common import AgentCheckTest | ||
|
||
INSTANCE = { | ||
'host': '.', | ||
'services': ['EventLog', 'Dnscache', 'NonExistingService'], | ||
} | ||
|
||
INVALID_HOST_INSTANCE = { | ||
'host': 'nonexistinghost', | ||
'services': ['EventLog'], | ||
} | ||
|
||
|
||
@attr('windows') | ||
@attr(requires='windows') | ||
class WindowsServiceTest(AgentCheckTest): | ||
CHECK_NAME = 'windows_service' | ||
|
||
SERVICE_CHECK_NAME = 'windows_service.state' | ||
|
||
def test_basic_check(self): | ||
self.run_check({'instances': [INSTANCE]}) | ||
self.assertServiceCheckOK(self.SERVICE_CHECK_NAME, tags=['service:EventLog'], count=1) | ||
self.assertServiceCheckOK(self.SERVICE_CHECK_NAME, tags=['service:Dnscache'], count=1) | ||
self.assertServiceCheckCritical(self.SERVICE_CHECK_NAME, tags=['service:NonExistingService'], count=1) | ||
self.coverage_report() | ||
|
||
def test_invalid_host(self): | ||
self.run_check({'instances': [INVALID_HOST_INSTANCE]}) | ||
self.assertServiceCheckCritical(self.SERVICE_CHECK_NAME, tags=['host:nonexistinghost', 'service:EventLog'], count=1) | ||
self.coverage_report() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,91 @@ | ||
# stdlib | ||
import copy | ||
|
||
# 3p | ||
from mock import Mock | ||
from nose.plugins.attrib import attr | ||
|
||
# project | ||
from tests.checks.common import AgentCheckTest | ||
|
||
INSTANCE = { | ||
'class': 'Win32_PerfFormattedData_PerfProc_Process', | ||
'metrics': [ | ||
['ThreadCount', 'proc.threads.count', 'gauge'], | ||
['IOReadBytesPerSec', 'proc.io.bytes_read', 'gauge'], | ||
['VirtualBytes', 'proc.mem.virtual', 'gauge'], | ||
['PercentProcessorTime', 'proc.cpu_pct', 'gauge'], | ||
], | ||
'tag_by': 'Name', | ||
} | ||
|
||
INSTANCE_METRICS = [ | ||
'proc.threads.count', | ||
'proc.io.bytes_read', | ||
'proc.mem.virtual', | ||
'proc.cpu_pct', | ||
] | ||
|
||
|
||
@attr('windows') | ||
@attr(requires='windows') | ||
class WMICheckTest(AgentCheckTest): | ||
CHECK_NAME = 'wmi_check' | ||
|
||
def test_basic_check(self): | ||
instance = copy.deepcopy(INSTANCE) | ||
instance['filters'] = [{'Name': 'svchost'}] | ||
self.run_check({'instances': [instance]}) | ||
|
||
for metric in INSTANCE_METRICS: | ||
self.assertMetric(metric, tags=['name:svchost'], count=1) | ||
|
||
self.coverage_report() | ||
|
||
def test_check_with_wildcard(self): | ||
instance = copy.deepcopy(INSTANCE) | ||
instance['filters'] = [{'Name': 'svchost%'}] | ||
self.run_check({'instances': [instance]}) | ||
|
||
for metric in INSTANCE_METRICS: | ||
# We can assume that at least 2 svchost processes are running | ||
self.assertMetric(metric, tags=['name:svchost'], count=1) | ||
self.assertMetric(metric, tags=['name:svchost#1'], count=1) | ||
|
||
def test_check_with_tag_queries(self): | ||
instance = copy.deepcopy(INSTANCE) | ||
instance['filters'] = [{'Name': 'svchost%'}] | ||
instance['tag_queries'] = [['IDProcess', 'Win32_Process', 'Handle', 'CommandLine']] | ||
self.run_check({'instances': [instance]}) | ||
|
||
for metric in INSTANCE_METRICS: | ||
# No instance "number" (`#`) when tag_queries is specified | ||
self.assertMetricTag(metric, tag='name:svchost#1', count=0) | ||
self.assertMetricTag(metric, tag='name:svchost') | ||
self.assertMetricTagPrefix(metric, tag_prefix='commandline:') | ||
|
||
def test_invalid_class(self): | ||
instance = copy.deepcopy(INSTANCE) | ||
instance['class'] = 'Unix' | ||
logger = Mock() | ||
|
||
self.run_check({'instances': [instance]}, mocks={'log': logger}) | ||
|
||
# A warning is logged | ||
self.assertEquals(logger.warning.call_count, 1) | ||
|
||
# No metrics/service check | ||
self.coverage_report() | ||
|
||
def test_invalid_metrics(self): | ||
instance = copy.deepcopy(INSTANCE) | ||
instance['metrics'].append(['InvalidProperty', 'proc.will.not.be.reported', 'gauge']) | ||
logger = Mock() | ||
|
||
self.run_check({'instances': [instance]}, mocks={'log': logger}) | ||
|
||
# A warning is logged | ||
self.assertEquals(logger.warning.call_count, 1) | ||
|
||
# No metrics/service check | ||
self.coverage_report() |
Oops, something went wrong.