• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

mendersoftware / mender-server / 1833359013

23 May 2025 01:25PM UTC coverage: 66.318% (+0.5%) from 65.861%
1833359013

Pull #674

gitlab-ci

mzedel
fix(gui): prevented device tag editor to be shown when no tags exist

- this is to reduce confusion about tags defined async to the current session not being visible

Ticket: ME-528
Signed-off-by: Manuel Zedel <manuel.zedel@northern.tech>
Pull Request #674: ME-529, ME-528 - adjustments to device tag editing

29554 of 44564 relevant lines covered (66.32%)

1.45 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

82.35
/backend/pkg/mongo/doc/ops.go
1
// Copyright 2023 Northern.tech AS
2
//
3
//    Licensed under the Apache License, Version 2.0 (the "License");
4
//    you may not use this file except in compliance with the License.
5
//    You may obtain a copy of the License at
6
//
7
//        http://www.apache.org/licenses/LICENSE-2.0
8
//
9
//    Unless required by applicable law or agreed to in writing, software
10
//    distributed under the License is distributed on an "AS IS" BASIS,
11
//    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
//    See the License for the specific language governing permissions and
13
//    limitations under the License.
14

15
package doc
16

17
import (
18
        "fmt"
19
        "reflect"
20
        "sort"
21

22
        "go.mongodb.org/mongo-driver/bson"
23
)
24

25
const (
26
        // PermutationThreshold limits the complexity of Unwound maps to the
27
        // given array length.
28
        PermutationThreshold = 1024
29
)
30

31
var (
32
        // ErrPermutations is returned if the map contains arrays with a combined
33
        // number of permutations than the threshold.
34
        ErrPermutations = fmt.Errorf(
35
                "object complexity (array permutations) exceeded threshold")
36
)
37

38
// item is an internally used struct to organize the output in UnwindMap
39
type item struct {
40
        Key   string
41
        Value reflect.Value
42
}
43

44
// UnwindMap takes a string map and perform mongodb $unwind aggregation operation
45
// on all array entries.
46
// Don't return a map - but a sorted list of tuples; mongo indices are sensitive
47
// to order.
48
// Example:
49
//
50
//        {"foo": ["1", "2"], "bar": "3"} becomes
51
//        [ {{"foo", "1", "bar", "3"}}, {{"foo": "2", "bar": "3"}} ]
52
func UnwindMap(
53
        in interface{},
54
) ([]bson.D, error) {
2✔
55
        // returned bloated map
2✔
56
        var unwoundMap []bson.D
2✔
57
        // permutations and cumulative sum of permutations
2✔
58
        var permutations int64 = 1
2✔
59

2✔
60
        inVal := reflect.ValueOf(in)
2✔
61
        if inVal.Kind() != reflect.Map {
2✔
62
                return nil, fmt.Errorf(
×
63
                        "invalid argument type: %s != map[string]interface{}",
×
64
                        inVal.Kind().String())
×
65
        }
×
66
        mapLen := inVal.Len()
2✔
67
        orderedMap := make([]item, mapLen)
2✔
68

2✔
69
        // Compute number of permutations and initialize ordered map.
2✔
70
        var i int
2✔
71
        keys := inVal.MapKeys()
2✔
72
        for _, key := range keys {
4✔
73
                var keyStr string
2✔
74
                var ok bool
2✔
75
                value := inVal.MapIndex(key)
2✔
76
                if key.Kind() == reflect.Interface {
2✔
77
                        key = key.Elem()
×
78
                }
×
79
                if value.Kind() == reflect.Interface {
4✔
80
                        value = value.Elem()
2✔
81
                }
2✔
82
                if keyStr, ok = key.Interface().(string); !ok {
2✔
83
                        return nil, fmt.Errorf("invalid argument type: "+
×
84
                                "%s != map[string]interface{}", inVal.Kind())
×
85
                }
×
86

87
                switch value.Kind() {
2✔
88
                case reflect.Slice, reflect.Array:
2✔
89
                        orderedMap[i] = item{
2✔
90
                                Key: keyStr,
2✔
91
                        }
2✔
92
                        prevPermutations := permutations
2✔
93
                        permutations = permutations * int64(value.Len())
2✔
94

2✔
95
                        // Check with constraint or overflow
2✔
96
                        if permutations > PermutationThreshold ||
2✔
97
                                permutations < prevPermutations {
2✔
98
                                return nil, ErrPermutations
×
99
                        }
×
100

101
                case reflect.String:
1✔
102
                        orderedMap[i] = item{
1✔
103
                                Key: keyStr,
1✔
104
                        }
1✔
105
                default:
×
106
                        return nil, fmt.Errorf(
×
107
                                "cannot unwind entry %s of type: %s",
×
108
                                key, value.Kind().String())
×
109
                }
110
                orderedMap[i].Value = value
2✔
111
                i++
2✔
112
        }
113

114
        sort.Slice(orderedMap, func(i, j int) bool {
3✔
115
                return orderedMap[i].Key < orderedMap[j].Key
1✔
116
        })
1✔
117

118
        // Allocate returned map array
119
        unwoundMap = make([]bson.D, permutations)
2✔
120

2✔
121
        // Fill in the map entries
2✔
122
        for k := int64(0); k < permutations; k++ {
4✔
123
                var tmpPerm int64 = 1
2✔
124
                unwoundMap[k] = make(bson.D, mapLen)
2✔
125
                for i, item := range orderedMap {
4✔
126
                        unwoundMap[k][i].Key = item.Key
2✔
127
                        itemKind := item.Value.Kind()
2✔
128
                        if itemKind == reflect.Slice ||
2✔
129
                                itemKind == reflect.Array {
4✔
130

2✔
131
                                // Compute index
2✔
132
                                // - think of it as counting using array
2✔
133
                                //   length as base
2✔
134
                                itemLen := item.Value.Len()
2✔
135
                                idx := (k / tmpPerm) % int64(itemLen)
2✔
136

2✔
137
                                unwoundMap[k][i].Value = item.Value.
2✔
138
                                        Index(int(idx)).Interface()
2✔
139

2✔
140
                                // Update cumulative permutations
2✔
141
                                tmpPerm *= int64(itemLen)
2✔
142
                        } else {
3✔
143
                                unwoundMap[k][i].Value = item.Value.Interface()
1✔
144
                        }
1✔
145
                }
146
        }
147
        return unwoundMap, nil
2✔
148
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc