@@ -11,10 +11,8 @@ import (
1111 "testing"
1212 "time"
1313
14- "github.com/ovh/cds/engine/api/repositoriesmanager"
15- "github.com/ovh/cds/engine/api/services"
16- "github.com/ovh/cds/engine/service"
17-
14+ "github.com/go-gorp/gorp"
15+ "github.com/golang/mock/gomock"
1816 "github.com/stretchr/testify/assert"
1917 "github.com/stretchr/testify/require"
2018 "gopkg.in/yaml.v2"
@@ -26,9 +24,13 @@ import (
2624 "github.com/ovh/cds/engine/api/integration"
2725 "github.com/ovh/cds/engine/api/pipeline"
2826 "github.com/ovh/cds/engine/api/project"
27+ "github.com/ovh/cds/engine/api/repositoriesmanager"
28+ "github.com/ovh/cds/engine/api/services"
29+ "github.com/ovh/cds/engine/api/services/mock_services"
2930 "github.com/ovh/cds/engine/api/test"
3031 "github.com/ovh/cds/engine/api/test/assets"
3132 "github.com/ovh/cds/engine/api/workflow"
33+ "github.com/ovh/cds/engine/service"
3234 "github.com/ovh/cds/sdk"
3335 "github.com/ovh/cds/sdk/cdsclient"
3436 "github.com/ovh/cds/sdk/exportentities"
@@ -1593,3 +1595,235 @@ func TestBenchmarkGetWorkflowsWithAPI(t *testing.T) {
15931595 t .Logf ("ns/op : %d" , res .NsPerOp ())
15941596 assert .False (t , res .NsPerOp () >= 500000000 , "Workflows load is too long: GOT %d and EXPECTED lower than 500000000 (500ms)" , res .NsPerOp ())
15951597}
1598+
1599+ func Test_putWorkflowShouldNotCallHOOKSIfHookDoesNotChange (t * testing.T ) {
1600+ api , db , router , end := newTestAPI (t )
1601+ defer end ()
1602+
1603+ _ , _ = assets .InsertService (t , db , t .Name ()+ "_HOOKS" , services .TypeHooks )
1604+
1605+ u , pass := assets .InsertAdminUser (t , api .mustDB ())
1606+ key := sdk .RandomString (10 )
1607+ proj := assets .InsertTestProject (t , db , api .Cache , key , key )
1608+ pip := sdk.Pipeline {
1609+ Name : "pipeline1" ,
1610+ ProjectID : proj .ID ,
1611+ }
1612+ assert .NoError (t , pipeline .InsertPipeline (db , & pip ))
1613+
1614+ wf := sdk.Workflow {
1615+ ProjectID : proj .ID ,
1616+ ProjectKey : proj .Key ,
1617+ Name : sdk .RandomString (10 ),
1618+ Groups : proj .ProjectGroups ,
1619+ WorkflowData : sdk.WorkflowData {
1620+ Node : sdk.Node {
1621+ Name : "root" ,
1622+ Context : & sdk.NodeContext {
1623+ PipelineID : pip .ID ,
1624+ },
1625+ Hooks : []sdk.NodeHook {
1626+ {
1627+ HookModelID : sdk .WebHookModel .ID ,
1628+ Config : sdk.WorkflowNodeHookConfig {
1629+ "method" : sdk.WorkflowNodeHookConfigValue {
1630+ Value : "POST" ,
1631+ },
1632+ },
1633+ },
1634+ },
1635+ },
1636+ },
1637+ }
1638+
1639+ // Setup a mock for all services called by the API
1640+ ctrl := gomock .NewController (t )
1641+ defer ctrl .Finish ()
1642+ // The mock has been geenrated by mockgen: go get github.com/golang/mock/mockgen
1643+ // If you have to regenerate thi mock you just have to run, from directory $GOPATH/src/github.com/ovh/cds/engine/api/services:
1644+ // mockgen -source=http.go -destination=mock_services/services_mock.go Client
1645+ servicesClients := mock_services .NewMockClient (ctrl )
1646+ services .NewClient = func (_ gorp.SqlExecutor , _ []sdk.Service ) services.Client {
1647+ return servicesClients
1648+ }
1649+ defer func () {
1650+ services .NewClient = services .NewDefaultClient
1651+ }()
1652+
1653+ // Mock the Hooks service
1654+ servicesClients .EXPECT ().
1655+ DoJSONRequest (gomock .Any (), "POST" , "/task/bulk" , gomock .Any (), gomock .Any ()).
1656+ DoAndReturn (
1657+ func (ctx context.Context , method , path string , in interface {}, out interface {}) (http.Header , int , error ) {
1658+ actualHooks , ok := in .(map [string ]sdk.NodeHook )
1659+ require .True (t , ok )
1660+ require .Len (t , actualHooks , 1 )
1661+ for k , h := range actualHooks {
1662+ h .Config ["method" ] = sdk.WorkflowNodeHookConfigValue {
1663+ Value : "POST" ,
1664+ Configurable : true ,
1665+ }
1666+ actualHooks [k ] = h
1667+ }
1668+ out = actualHooks
1669+ return nil , 200 , nil
1670+ },
1671+ )
1672+
1673+ // Insert the workflow
1674+ vars := map [string ]string {
1675+ "permProjectKey" : proj .Key ,
1676+ }
1677+ uri := router .GetRoute ("POST" , api .postWorkflowHandler , vars )
1678+ test .NotEmpty (t , uri )
1679+ req := assets .NewAuthentifiedRequest (t , u , pass , "POST" , uri , & wf )
1680+ w := httptest .NewRecorder ()
1681+ router .Mux .ServeHTTP (w , req )
1682+ assert .Equal (t , 201 , w .Code )
1683+
1684+ // Load the workflow
1685+ vars = map [string ]string {
1686+ "key" : proj .Key ,
1687+ "permWorkflowName" : wf .Name ,
1688+ }
1689+ uri = router .GetRoute ("GET" , api .getWorkflowHandler , vars )
1690+ test .NotEmpty (t , uri )
1691+ req = assets .NewAuthentifiedRequest (t , u , pass , "GET" , uri , nil )
1692+ w = httptest .NewRecorder ()
1693+ router .Mux .ServeHTTP (w , req )
1694+
1695+ // Unmarshal the workflow
1696+ require .NoError (t , json .Unmarshal (w .Body .Bytes (), & wf ))
1697+
1698+ // Then call the PUT handler, it should not trigger /task/bulk on hooks service
1699+ // Update the workflow
1700+ uri = router .GetRoute ("PUT" , api .putWorkflowHandler , vars )
1701+ test .NotEmpty (t , uri )
1702+ req = assets .NewAuthentifiedRequest (t , u , pass , "PUT" , uri , & wf )
1703+ w = httptest .NewRecorder ()
1704+ router .Mux .ServeHTTP (w , req )
1705+ assert .Equal (t , 200 , w .Code )
1706+
1707+ }
1708+
1709+ func Test_putWorkflowWithDuplicateHooksShouldRaiseAnError (t * testing.T ) {
1710+ api , db , router , end := newTestAPI (t )
1711+ defer end ()
1712+
1713+ _ , _ = assets .InsertService (t , db , t .Name ()+ "_HOOKS" , services .TypeHooks )
1714+
1715+ u , pass := assets .InsertAdminUser (t , api .mustDB ())
1716+ key := sdk .RandomString (10 )
1717+ proj := assets .InsertTestProject (t , db , api .Cache , key , key )
1718+ pip := sdk.Pipeline {
1719+ Name : "pipeline1" ,
1720+ ProjectID : proj .ID ,
1721+ }
1722+ assert .NoError (t , pipeline .InsertPipeline (db , & pip ))
1723+
1724+ wf := sdk.Workflow {
1725+ ProjectID : proj .ID ,
1726+ ProjectKey : proj .Key ,
1727+ Name : sdk .RandomString (10 ),
1728+ Groups : proj .ProjectGroups ,
1729+ WorkflowData : sdk.WorkflowData {
1730+ Node : sdk.Node {
1731+ Name : "root" ,
1732+ Context : & sdk.NodeContext {
1733+ PipelineID : pip .ID ,
1734+ },
1735+ Hooks : []sdk.NodeHook {
1736+ {
1737+ HookModelID : sdk .WebHookModel .ID ,
1738+ Config : sdk.WorkflowNodeHookConfig {
1739+ "method" : sdk.WorkflowNodeHookConfigValue {
1740+ Value : "POST" ,
1741+ },
1742+ },
1743+ },
1744+ },
1745+ },
1746+ },
1747+ }
1748+
1749+ // Setup a mock for all services called by the API
1750+ ctrl := gomock .NewController (t )
1751+ defer ctrl .Finish ()
1752+ // The mock has been geenrated by mockgen: go get github.com/golang/mock/mockgen
1753+ // If you have to regenerate thi mock you just have to run, from directory $GOPATH/src/github.com/ovh/cds/engine/api/services:
1754+ // mockgen -source=http.go -destination=mock_services/services_mock.go Client
1755+ servicesClients := mock_services .NewMockClient (ctrl )
1756+ services .NewClient = func (_ gorp.SqlExecutor , _ []sdk.Service ) services.Client {
1757+ return servicesClients
1758+ }
1759+ defer func () {
1760+ services .NewClient = services .NewDefaultClient
1761+ }()
1762+
1763+ // Mock the Hooks service
1764+ servicesClients .EXPECT ().
1765+ DoJSONRequest (gomock .Any (), "POST" , "/task/bulk" , gomock .Any (), gomock .Any ()).
1766+ DoAndReturn (
1767+ func (ctx context.Context , method , path string , in interface {}, out interface {}) (http.Header , int , error ) {
1768+ actualHooks , ok := in .(map [string ]sdk.NodeHook )
1769+ require .True (t , ok )
1770+ require .Len (t , actualHooks , 1 )
1771+ for k , h := range actualHooks {
1772+ h .Config ["method" ] = sdk.WorkflowNodeHookConfigValue {
1773+ Value : "POST" ,
1774+ Configurable : true ,
1775+ }
1776+ actualHooks [k ] = h
1777+ }
1778+ out = actualHooks
1779+ return nil , 200 , nil
1780+ },
1781+ )
1782+
1783+ // Insert the workflow
1784+ vars := map [string ]string {
1785+ "permProjectKey" : proj .Key ,
1786+ }
1787+ uri := router .GetRoute ("POST" , api .postWorkflowHandler , vars )
1788+ test .NotEmpty (t , uri )
1789+ req := assets .NewAuthentifiedRequest (t , u , pass , "POST" , uri , & wf )
1790+ w := httptest .NewRecorder ()
1791+ router .Mux .ServeHTTP (w , req )
1792+ assert .Equal (t , 201 , w .Code )
1793+
1794+ // Load the workflow
1795+ vars = map [string ]string {
1796+ "key" : proj .Key ,
1797+ "permWorkflowName" : wf .Name ,
1798+ }
1799+ uri = router .GetRoute ("GET" , api .getWorkflowHandler , vars )
1800+ test .NotEmpty (t , uri )
1801+ req = assets .NewAuthentifiedRequest (t , u , pass , "GET" , uri , nil )
1802+ w = httptest .NewRecorder ()
1803+ router .Mux .ServeHTTP (w , req )
1804+
1805+ // Unmarshal the workflow
1806+ require .NoError (t , json .Unmarshal (w .Body .Bytes (), & wf ))
1807+
1808+ // Then add another hooks with similar properties. It should raise a 400 HTTP Error
1809+
1810+ wf .WorkflowData .Node .Hooks = append (wf .WorkflowData .Node .Hooks ,
1811+ sdk.NodeHook {
1812+ HookModelID : sdk .WebHookModel .ID ,
1813+ Config : sdk.WorkflowNodeHookConfig {
1814+ "method" : sdk.WorkflowNodeHookConfigValue {
1815+ Value : "POST" ,
1816+ },
1817+ },
1818+ },
1819+ )
1820+
1821+ // Update the workflow
1822+ uri = router .GetRoute ("PUT" , api .putWorkflowHandler , vars )
1823+ test .NotEmpty (t , uri )
1824+ req = assets .NewAuthentifiedRequest (t , u , pass , "PUT" , uri , & wf )
1825+ w = httptest .NewRecorder ()
1826+ router .Mux .ServeHTTP (w , req )
1827+ assert .Equal (t , 400 , w .Code )
1828+
1829+ }
0 commit comments